[转]文件上传进度显示

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[转]文件上传进度显示相关的知识,希望对你有一定的参考价值。

原文: http://www.codeguru.com/java/article.php/c13913/AJAX-File-Upload-Progress-for-Java.htm#page-1

文件上传需要用到commons-fileupload-1.2.1.jar

技术分享

技术分享

首先创建一个FileUploadServlet文件

 1     package com.psclistens.ajax.fileupload;
 2      
 3     import java.io.File;
 4     import java.io.IOException;
 5     import java.io.PrintWriter;
 6     import java.util.Iterator;
 7     import java.util.List;
 8     import javax.servlet.Servlet;
 9     import javax.servlet.ServletException;
10     import javax.servlet.http.HttpServlet;
11     import javax.servlet.http.HttpServletRequest;
12     import javax.servlet.http.HttpServletResponse;
13     import javax.servlet.http.HttpSession;
14     import org.apache.commons.fileupload.FileItem;
15     import org.apache.commons.fileupload.FileItemFactory;
16     import org.apache.commons.fileupload.FileUploadException;
17     import org.apache.commons.fileupload.disk.DiskFileItemFactory;
18     import org.apache.commons.fileupload.servlet.ServletFileUpload;
19      
20     /**
21      * This is a File Upload Servlet that is used with AJAX
22      * to monitor the progress of the uploaded file. It will
23      * return an XML object containing the meta information
24      * as well as the percent complete.
25      */
26     public class FileUploadServlet
27        extends HttpServlet
28        implements Servlet
29     {
30        private static final long serialVersionUID = 2740693677625051632L;
31      
32        public FileUploadServlet()
33        {
34           super();
35        }
36      
37        protected void doGet(HttpServletRequest request,
38                             HttpServletResponse response)
39           throws ServletException, IOException
40        {
41        }
42      
43        protected void doPost(HttpServletRequest request,
44                              HttpServletResponse response)
45           throws ServletException, IOException
46        {
47        }
48     }

修改 web.xml 文件添加servlet配置

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app id="WebApp_ID" version="2.4" 
       xmlns="http://java.sun.com/xml/ns/j2ee" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
       xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
          http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
       <display-name>AJAXFileUploadApp</display-name>
     
       <servlet>
          <description>Servlet for file uploads</description>
          <display-name>File Upload Servlet</display-name>
          <servlet-name>>FileUploadServlet</servlet-name> 
          <servlet-class>
             com.psclistens.ajax.fileupload.FileUploadServlet
          </servlet-class>
       </servlet>
     
       <servlet-mapping>
          <servlet-name>FileUploadServlet</servlet-name>
          <url-pattern>/servlet/FileUploadServlet</url-pattern>
       </servlet-mapping>
     
       <welcome-file-list>
          <welcome-file>fileUpload.html</welcome-file>
       </welcome-file-list>
    </web-app>

接着,创建一个文件上传的监听,监听继承自org.apache.commons.fileupload.ProgressListener

    package com.psclistens.ajax.fileupload;
     
    import org.apache.commons.fileupload.ProgressListener;
     
    /**
     * This is a File Upload Listener that is used by Apache
     * Commons File Upload to monitor the progress of the 
     * uploaded file.
     */
    public class FileUploadListener 
       implements ProgressListener
    {
       private volatile long 
          bytesRead = 0L,
          contentLength = 0L,
          item = 0L;   
     
        public FileUploadListener() 
       {
          super();
       }
     
       public void update(long aBytesRead, long aContentLength,
                          int anItem)
       {
          bytesRead = aBytesRead;
          contentLength = aContentLength;
          item = anItem;
       }
     
       public long getBytesRead() 
       {
          return bytesRead;
       }
     
       public long getContentLength() 
       {
          return contentLength;
       }
     
       public long getItem() 
       {
          return item;
       }
    }

 修改servlet中的doPost方法为下面代码

       protected void doPost(HttpServletRequest request,
                             HttpServletResponse response)
          throws ServletException, IOException
       {
          // create file upload factory and upload servlet
          FileItemFactory
             factory = new DiskFileItemFactory();
          ServletFileUpload
             upload = new ServletFileUpload(factory);
     
          // set file upload progress listener
          FileUploadListener
             listener = new FileUploadListener();
     
          HttpSession
             session = request.getSession();
     
          session.setAttribut("LISTENER", listener);
     
          // upload servlet allows to set upload listener
          upload.setProgressListener(listener);
     
          List
             uploadedItems = null;
          FileItem
             fileItem = null;
          String
             // Path to store file on local system
             filePath = "c:\\temp";
     
          try
          {
             // iterate over all uploaded files
             uploadedItems = upload.parseRequest(request);
     
             Iterator
                i = uploadedItems.iterator();
     
             while (i.hasNext())
             {
                fileItem = (FileItem) i.next();
     
                if (fileItem.isFormField() == false)
                {
                   if (fileItem.getSize() > 0)
                   {
                      File
                         uploadedFile = null;
                      String
                         myFullFileName = fileItem.getName(),
                         myFileName = "",
                         slashType = (myFullFileName.lastIndexOf("\\")
                            > 0) ? "\\" : "/";    // Windows or UNIX
                      int
                         startIndex =
                            myFullFileName.lastIndexOf(slashType);
     
                      // Ignore the path and get the filename
                      myFileName = myFullFileName.substring
                        (startIndex + 1, myFullFileName.length());
     
                      // Create new File object
                      uploadedFile = new File(filePath, myFileName);
     
                      // Write the uploaded file to the system
                      fileItem.write(uploadedFile);
                   }
                }
             }
          }
          catch (FileUploadException e)
          {
             e.printStackTrace();
          }
          catch (Exception e)
          {
             e.printStackTrace();
          }
       }

创建上传的html页面,上传完成后跳转至当前页面隐藏的iframe中,从而实现实现当前页面不刷新

    <html>
    <head>
    <title>Ajax File Upload</title>
    </head>
    <body>
       <iframe id="uploadFrameID"
               name="uploadFrame"
               height="0" width="0"
               frameborder="0"
               scrolling="yes"></iframe>
       <form id="myForm"
             enctype="multipart/form-data"
             method="post"
             target="uploadFrame"
             action="servlet/FileUploadServlet"
             onsubmit="ajaxFunction()">
       <input type="file"
              name="txtFile"
              id="txtFile" /><br />
       <input type="submit"
              id="submitID"
              name="submit"
              value="Upload" />
       </form>
    </body>
    </html>

添加一个隐藏的div,当上传表单提交的时候,显示该div作为进度的显示。

<div id="initializing"
     style="visibility: hidden; position: absolute; top: 100px;">
   <table width="100%"
          style="border: 1px; background-color: black;">
      <tr>
         <td>
            <table width="100%"
                   style="border: 1px; background-color: black;
                          color: white;">
               <tr>
                  <td align="center">
                     <b>Initializing Upload...</b>
                  </td>
               </tr>
            </table>
         </td>
      </tr>
   </table>
</div>
 
<div id="progressBarTable"
     style="visibility: hidden; position: absolute; top: 100px;">
   <table width="100%"
          style="border: 1px; background-color: black;
                 color: white;">
      <tr>
         <td>
            <table id="progressBar" width="0px" 
               style="border: 1px; width: 0px;
                      background-color: blue;">
                  <tr>
                     <td>&nbsp;</td>
               </tr>
            </table>
         </td>
      </tr>
   </table>
   <table width="100%"
          style="background-color: white; color: black;">
      <tr>
         <td align="center" nowrap="nowrap">
            <span id="bytesRead"
                  style="font-weight: bold;">&nbsp;</span>
         </td>
      </tr>
   </table>
</div>
 
<div id="percentCompleteTable" align="center"
   style="visibility: hidden; position: absolute; top: 100px;">
   <table width="100%" style="border: 1px;">
      <tr>
         <td>
            <table width="100%" style="border: 1px;">
               <tr>
                  <td align="center" nowrap="nowrap">
                     <span id="percentComplete"
                           style="color: white; font-weight:
                                  bold;">&nbsp;</span>
                  </td>
               </tr>
            </table>
         </td>
      </tr>
   </table>
</div>

修改servlet的doGet方法,返回XHR数据作为ajax请求的数据。

    protected void doGet(HttpServletRequest request,
                         HttpServletResponse response)
       throws ServletException, IOException
    {
       PrintWriter
          out = response.getWriter();
       HttpSession
          session = request.getSession();
       FileUploadListener
          listener = null;
       StringBuffer
          buffy = new StringBuffer();
       long
          bytesRead = 0,
          contentLength = 0;
     
       // Make sure the session has started
       if (session == null)
       {
          return;
       }
       else if (session != null)
       {
          // Check to see if we‘ve created the listener object yet
          listener =
             (FileUploadListener)session.getAttribute("LISTENER");
     
          if (listener == null)
          {
             return;
          }
          else
          {
             // Get the meta information
             bytesRead = listener.getBytesRead();
             contentLength = listener.getContentLength();
          }
       }
     
       response.setContentType("text/xml");
     
       buffy.append("<?xml version=\"1.0\"
                     encoding=\"ISO-8859-1\"?>\n");
       buffy.append("<response>\n");
       buffy.append("\t<bytes_read>" + bytesRead + "</bytes_read>\n");
       buffy.append("\t<content_length>" + contentLength +
                    "</content_length>\n");
     
       // Check to see if we‘re done
       if (bytesRead == contentLength)
       {
          buffy.append("\t<finished />\n");
     
          // No reason to keep listener in session since we‘re done
          session.setAttribute("LISTENER", null);
       }
       else
       {
          // Calculate the percent complete
          long percentComplete = ((100 * bytesRead) / contentLength);
     
          buffy.append("\t<percent_complete>" + percentComplete +
                       "</percent_complete>\n");
       }
     
       buffy.append("</response>\n");
     
       out.println(buffy.toString());
       out.flush();
       out.close();
    }

添加ajax代码:

    <script language="javascript">
    var req;
     
    function ajaxFunction()
    {
       var url = "servlet/FileUploadServlet";
     
       if (window.XMLHttpRequest)        // Non-IE browsers
       {
          req = new XMLHttpRequest();
          req.onReadyStateChange = processStateChange;
     
          try
          {
             req.open("GET", url, true);
          } 
          catch (e) 
          {
                alert(e);
          }
          req.send(null);
       }
       else if (window.ActiveXObject)    // IE Browsers
       {
          req = new ActiveXObject("Microsoft.XMLHTTP");
     
          if (req) 
          {
                req.onReadyStateChange = processStateChange;
                req.open("GET", url, true);
                req.send();
          }
       }
    }
    function processStateChange()
    {
       /**
       *  State    Description
       *    0      The request is not initialized
       *    1      The request has been set up
       *    2      The request has been sent
       *    3      The request is in process
       *    4      The request is complete
       */
       if (req.readyState == 4)
       {
          if (req.status == 200) // OK response
          {
             var xml = req.responseXML;
     
             // No need to iterate since there will only be one set
             // of lines
             var isNotFinished =
                xml.getElementsByTagName("finished")[0];
             var myBytesRead =
                xml.getElementsByTagName("bytes_read")[0];
             var myContentLength =
                xml.getElementsByTagName("content_length")[0];
             var myPercent =
                xml.getElementsByTagName("percent_complete")[0];
     
             // Check to see if it‘s even started yet
             if ((isNotFinished == null) && (myPercent == null))
             {
                   document.getElementById
                      ("initializing").style.visibility = "visible";
     
                   // Sleep then call the function again
                   window.setTimeout("ajaxFunction();", 100);
                }
             else 
             {
                 document.getElementById("initializing" ).
                    style.visibility = "hidden";
                 document.getElementById("progressBarTable" ).
                    style.visibility = "visible";
                 document.getElementById("percentCompleteTable" ).
                    style.visibility = "visible";
                 document.getElementById("bytesRead" ).
                    style.visibility = "visible";
     
                 myBytesRead = myBytesRead.firstChild.data;
                 myContentLength = myContentLength.firstChild.data;
     
                 // It‘s started, get the status of the upload
                 if (myPercent != null)
                 {
                    myPercent = myPercent.firstChild.data;
     
                    document.getElementById("progressBar").style.width =
                       myPercent + "%";
                    document.getElementById("bytesRead").innerHTML =
                       myBytesRead + " of " + 
                       myContentLength + " bytes read";
                    document.getElementById("percentComplete").innerHTML =
                       myPercent + "%";
     
                    // Sleep then call the function again
                    window.setTimeout("ajaxFunction();", 100);
                 }
                 else
                 {
                    document.getElementById("bytesRead").style.
                       visibility = "hidden";
                    document.getElementById("progressBar").style.width =
                       "100%";
                    document.getElementById("percentComplete").
                       innerHTML = "Done!";
                 }
                }
          }
          else
          {
                alert(req.statusText);
          }
       }
    }
    </script>

这样实现一个简易的ajax上传进度显示功能

以上是关于[转]文件上传进度显示的主要内容,如果未能解决你的问题,请参考以下文章

java多文件上传显示进度条

如何在ajax文件上传中显示进度条

文件上传显示进度(js代码实现,不适合多次中转显示)

文件上传和进度条

前端上传文件实时显示进度条和上传速度的工作原理是怎样的?

显示多文件上传 Jquery/Ajax 的进度