JavaWeb项目实现上传文件动态显示进度百分比

当我学习JavaWeb文件上传的时候,我就一直有一个疑问,网站上那些博客的图片是怎么上传的,因为当提交了表单之后网页就跳转了。后来我学习到了Ajax,我知道了浏览器可以异步的发送响应,这时我又有新的疑问,那就是在我上传一些文件的时候,那些网站的上传进度是怎么做到的,因为servlet直到上传完成之后才完成响应。

  最近我们的项目中有一个地方中需要用到一个功能,当用户点击一个处理按钮时,前台会实时的显示后台处理动态,由于servlet一次只能接受一个请求,而且在servlet的生命周期结束时才会把响应数据发送到前台(这一点大家可以做个这样的测试

response.getWriter().print("hello");
Thread.sleep(10000);
response.getWriter().print("world");

你们会发现前台在等待了约10s后收到了"helloworld")。所以我想到了一个方法:使用单例保存实时信息。具体的实现方法就是,当用户点击了处理按钮时,在后台开启一个线程进行处理,并且每进行到一步,就向单例中写入当前状态信息。然后编写一个servlet,用于返回单例中的信息,前台循环发送请求,这样就能实现实时显示进度的效果。

  好了,啰嗦了这么多,下面进入正题,如何实现上传文件动态显示进度,其实思想和上面的功能是一致的,我将这个功能分为三个点:

  1. 单例:用于保存进度信息;
  2. 上传servlet:用于上传文件并实时写入进度;
  3. 进度servlet:用于读取实时进度信息;
上代码,前台:



 
 
 Insert title here
 


    

File upload demo



  后台,单例:

import java.util.Hashtable;
 
public class ProgressSingleton {
    //为了防止多用户并发,使用线程安全的Hashtable
    private static Hashtable table = new Hashtable<>();
    
    public static void put(Object key, Object value){
        table.put(key, value);
    }
    
    public static Object get(Object key){
        return table.get(key);
    }
    
    public static Object remove(Object key){
        return table.remove(key);
    }
}
上传servlet:
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.tomcat.util.http.fileupload.FileItem;
import org.apache.tomcat.util.http.fileupload.FileUploadException;
import org.apache.tomcat.util.http.fileupload.disk.DiskFileItemFactory;
import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;
import org.apache.tomcat.util.http.fileupload.servlet.ServletRequestContext;
import singleton.ProgressSingleton;
@WebServlet("/UploadServlet")
public class UploadServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    public UploadServlet() {
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        
        DiskFileItemFactory factory = new DiskFileItemFactory();
        factory.setSizeThreshold(4*1024);
        
        ServletFileUpload upload = new ServletFileUpload(factory);
        
        List fileItems;
        try {
            fileItems = upload.parseRequest(new ServletRequestContext(request));
            //获取文件域
            FileItem fileItem = fileItems.get(0);
            //使用sessionid + 文件名生成文件号
            String id = request.getSession().getId() + fileItem.getName();
            //向单例哈希表写入文件长度和初始进度
            ProgressSingleton.put(id + "Size", fileItem.getSize());
            //文件进度长度
            long progress = 0;
            //用流的方式读取文件,以便可以实时的获取进度
            InputStream in = fileItem.getInputStream();
            File file = new File("D:/test");
            file.createNewFile();
            FileOutputStream out = new FileOutputStream(file);
            byte[] buffer = new byte[1024];
            int readNumber = 0;
            while((readNumber = in.read(buffer)) != -1){
                //每读取一次,更新一次进度大小
                progress = progress + readNumber;
                //向单例哈希表写入进度
                ProgressSingleton.put(id + "Progress", progress);
                out.write(buffer);
            }
            //当文件上传完成之后,从单例中移除此次上传的状态信息
            ProgressSingleton.remove(id + "Size");
            ProgressSingleton.remove(id + "Progress");
            in.close();
            out.close();
        } catch (FileUploadException e) {
            e.printStackTrace();
        }
        
        response.getWriter().print("done");
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}
 进度servlet:

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONObject;
import singleton.ProgressSingleton;
@WebServlet("/ProgressServlet")
public class ProgressServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
       
    public ProgressServlet() {
        super();
        // TODO Auto-generated constructor stub
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        
        String id = request.getSession().getId();
        String filename = request.getParameter("filename");
        //使用sessionid + 文件名生成文件号,与上传的文件保持一致
        id = id + filename;
        Object size = ProgressSingleton.get(id + "Size");
        size = size == null ? 100 : size;
        Object progress = ProgressSingleton.get(id + "Progress");
        progress = progress == null ? 0 : progress; 
        JSONObject json = new JSONObject();
        json.put("size", size);
        json.put("progress", progress);
        response.getWriter().print(json.toString());
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}
效果图:

JavaWeb项目实现上传文件动态显示进度百分比_第1张图片


源码链接点击下载源码


你可能感兴趣的:(java,java,web,文件上传进度条,ajax,tomcat)