JavaWeb项目实现文件上传动态显示进度
很久没有更新博客了,这段时间实在的忙的不可开交,项目马上就要上线了,要修补的东西太多了。当我在学习JavaWeb文件上传的时候,我就一直有一个疑问,网站上那些博客的图片是怎么上传的,因为当提交了表单之后网页就跳转了。后来我学习到了Ajax,我知道了浏览器可以异步的发送响应,这时我又有新的疑问,那就是在我上传一些文件的时候,那些网站的上传进度是怎么做到的,因为servlet直到上传完成之后才完成响应。
最近我们的项目中有一个地方中需要用到一个功能,当用户点击一个处理按钮时,前台会实时的显示后台处理动态,由于servlet一次只能接受一个请求,而且在servlet的生命周期结束时才会把响应数据发送到前台(这一点大家可以做个这样的测试:
- response.getWriter().print("hello");
- Thread.sleep(10000);
- response.getWriter().print("world");
,你们会发现前台在等待了约10s后收到了"helloworld")。所以我想到了一个方法:使用单例保存实时信息。具体的实现方法就是,当用户点击了处理按钮时,在后台开启一个线程进行处理,并且每进行到一步,就向单例中写入当前状态信息。然后编写一个servlet,用于返回单例中的信息,前台循环发送请求,这样就能实现实时显示进度的效果。
好了,啰嗦了这么多,下面进入正题,如何实现上传文件动态显示进度,其实思想和上面的功能是一致的,我将这个功能分为三个点:
- 单例:用于保存进度信息;
- 上传servlet:用于上传文件并实时写入进度;
- 进度servlet:用于读取实时进度信息;
上代码,前台:
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8">
- <title>Insert title here</title>
- <style type="text/css">
- #progress:after {
- content: '%';
- }
- </style>
- </head>
- <body>
- <h3>File upload demo</h3>
- <form action="TestServlet" method="post" enctype="multipart/form-data" id="dataForm">
- <input type="file" name="file" id="fileInput"> <br>
- <input type="submit" value="submit" id="submit">
- </form>
- <div id="progress"></div>
- <script type="text/javascript" src="scripts/jquery-1.9.1.min.js"></script>
- <script type="text/javascript">
- (function () {
- var form = document.getElementById("dataForm");
- var progress = document.getElementById("progress");
- $("#submit").click(function(event) {
- //阻止默认事件
- event.preventDefault();
- //循环查看状态
- var t = setInterval(function(){
- $.ajax({
- url: 'ProgressServlet',
- type: 'POST',
- dataType: 'text',
- data: {
- filename: fileInput.files[0].name,
- },
- success: function (responseText) {
- var data = JSON.parse(responseText);
- //前台更新进度
- progress.innerText = parseInt((data.progress / data.size) * 100);
- },
- error: function(){
- console.log("error");
- }
- });
- }, 500);
- //上传文件
- $.ajax({
- url: 'UploadServlet',
- type: 'POST',
- dataType: 'text',
- data: new FormData(form),
- processData: false,
- contentType: false,
- success: function (responseText) {
- //上传完成,清除循环事件
- clearInterval(t);
- //将进度更新至100%
- progress.innerText = 100;
- },
- error: function(){
- console.log("error");
- }
- });
- return false;
- });
- })();
- </script>
- </body>
- </html>
后台,单例:
- import java.util.Hashtable;
- public class ProgressSingleton {
- //为了防止多用户并发,使用线程安全的Hashtable
- private static Hashtable<Object, Object> 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<FileItem> 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项目实现文件上传动态显示进度的更多相关文章
- JavaWeb学习总结——文件上传和下载
在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...
- javaWeb中,文件上传和下载
在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...
- JavaWeb中的文件上传和下载功能的实现
导入相关支持jar包:commons-fileupload.jar,commons-io.jar 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用Servlet获取上 ...
- javaWeb中的文件上传下载
在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...
- 使用Typescript重构axios(二十五)——文件上传下载进度监控
0. 系列文章 1.使用Typescript重构axios(一)--写在最前面 2.使用Typescript重构axios(二)--项目起手,跑通流程 3.使用Typescript重构axios(三) ...
- atitit.文件上传带进度条的实现原理and组件选型and最佳实践总结O7
atitit.文件上传带进度条的实现原理and组件选型and最佳实践总结O7 1. 实现原理 1 2. 大的文件上传原理::使用applet 1 3. 新的bp 2 1. 性能提升---分割小文件上传 ...
- atitit. 文件上传带进度条 atiUP 设计 java c# php
atitit. 文件上传带进度条 atiUP 设计 java c# php 1. 设计要求 1 2. 原理and 架构 1 3. ui 2 4. spring mvc 2 5. springMVC.x ...
- SpringBoot项目实现文件上传和邮件发送
前言 本篇文章主要介绍的是SpringBoot项目实现文件上传和邮件发送的功能. SpringBoot 文件上传 说明:如果想直接获取工程那么可以直接跳到底部,通过链接下载工程代码. 开发准备 环境要 ...
- web项目的文件上传和 下载
文件上传和下载在web应用中非常普遍,要在jsp环境中实现文件上传功能是非常容易的,因为网上有许多用Java开发的文件上传组件,本文以commons-fileupload组件为例,为jsp应用添加文件 ...
随机推荐
- HDU---Labyrinth
Labyrinth Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...
- c++文件读取(一)---输入类使用和查找当前程序路径
鉴于公司人员流动大,设计一个小的日志定位器,首先要读取日志文件 用输入输出流类操作文件比c的stdio更安全和容易,当然任何此类观点都是对大牛除外 首先是查找当前文件路径,如果用GetCurrentD ...
- NDK 开发(Android.mk配置)
在我写这篇文章的时候,Android Studio已经是2.3版本了,已经集成CMake 编译工具, 用户只需在 新建项目的时候,添加选项(Include C++ support),Andr ...
- 从零开始部署小型企业级虚拟桌面 -- Vmware Horizon View 6 For Linux VDI -- 概念简介
什么是桌面虚拟化? 桌面虚拟化有很多概念,此处谈论的,是指的一般企业使用的“服务器 + 虚拟机 + 云终端”的方式来实现的. 桌面虚拟化的原理是什么? 桌面虚拟化看上去高大上,实际上原理非常的简单.拿 ...
- oracle目录操作
1.创建目录 create directory dir_name as 'dir_path' (dir_path必须事先手动创建) 2.授权 grant read,write on director ...
- java Thread和Runable的深刻理解
线程(Thread)是指程序的运行流程,多线程机制指同时运行多个程序块. Java中实现多线程有两种方法:继承Thread类:实现Runnable接口. Thread类的run()方法的制定者:接口R ...
- MD5加密 32位
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo } p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; ...
- struts2(二) 表单参数自动封装和参数类型自动转换
前篇文章对struts2的一个入门,重点是对struts2的架构图有一个大概的了解即可,之后的几篇文章,就是细化struts2,将struts2中的各种功能进行梳理,其实学完之后,对struts2的使 ...
- 设置border属性变化不同形状:三角形、圆形、弧形 2017-03-20
一.通过设置边框----正方形.三角形 <style> .c{ height: 0px; width: 0px; border-top: 50px solid red; border-ri ...
- Linux下httpd服务与Apache服务的查看和启动
转:http://jingyan.baidu.com/article/63f236282d43170209ab3d43.html 这里简要介绍Linux环境中Apache也就是httpd服务的启动,查 ...