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:用于读取实时进度信息;

上代码,前台:

<!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);
  }

}

效果图:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • javaWeb自定义标签用法实例详解

    本文实例讲述了javaWeb自定义标签用法.分享给大家供大家参考,具体如下: 自定义标签创建 自定义标签主要用于移除Jsp页面中的Java代码. 移除jsp页面中的java代码,只需要完成两个步骤: - 编写一个继承TagSupport的Java类,并覆盖doStartTag方法,把jsp页面中的java代码写到doStartTag方法中. - 编写标签库描述符(tld)文件,在tld文件中对自定义标签进行描述. 完成以上操作,即可在JSP页面中导入和使用自定义标签. 标签处理类:HelloTa

  • javaweb判断当前请求是否为移动设备访问的方法

    这段时间都是在做pc端的业务,结果经理找到我说,可能要做移动端的应用,后台逻辑还是用我写的逻辑,但是需要改动一些,看看怎么处理. 由于移动端和pc端还是稍微有些区别的,我觉得最好是在一个地儿统一判断,而且不要改动原先的代码,这样可以从一定程度上减少bug的数量.我的想法是首先应该判断当前请求是否为移动端,然后设一个标识到session中,然后就可以随便处理了.不管你是单独处理,还是统一处理,直接读取session就可以做相应的判断了. 我封装成了一个类,现在分享给大家: package com.

  • javaWeb项目部署到阿里云服务器步骤详解

    记录web项目部署到阿里云服务器步骤 (使用 web项目.阿里云服务器.Xftp.Xshell),敬请参考和指正 1.将要部署的项目打包成WAR文件格式,可以在MyEclipse.Eclipse都可以完成打包,如下图: 2.安装Xshell和Xftp两种软件 简单介绍下这两种软件作用(详情请百度相关文档) Xshell:通过网络连接到远程服务器主机. Xftp:能在Linux.Unix和Windows之间互传文件. 3.通过Xshell连接远程主机,如下图    4.创建会话完成,点击连接,显示

  • 关于javaWeb中405错误的解决方法

    今天写了一个servlet,可是一直405报错,开始以为web.xml里面的servlet配置有问题,可是那样的话应该报404错误啊 最后才发现在重写doPost和doGet方法的时候,写成了dopost和doget,因为java对大小写很敏感,故相当于没有重新httpservelt里面的方法. 反思:编程需谨慎!!! 以上这篇关于javaWeb中405错误的解决方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们.

  • JavaWeb使用POI操作Excel文件实例

    1.为项目添加POI POI官网链接 点进去之后下载(上边的是编译好的类,下边的是源代码) 解压文件夹,把下面三个文件复制到WebComtent>WEB-INF>lib文件夹下 再把这三个文件复制到Tomcat的lib文件夹下,否则Tomcat会因为找不到类而报错(这个地方郁闷了一上午) 读取".xls"格式使用  import org.apache.poi.hssf.usermodel.*;包的内容,例如:HSSFWorkbook 读取".xlsx"格

  • JavaWeb中web.xml初始化加载顺序详解

    需求说明 做项目时,为了省事,起初把初始化的配置都放在每个类中 static加载,初始化配置一多,就想把它给整理一下,这里使用servlet中的init方法初始化. web.xml说明 首先了解下web.xml中元素的加载顺序: 启动web项目后,web容器首先回去找web.xml文件,读取这个文件 容器会创建一个 ServletContext ( servlet 上下文),整个 web 项目的所有部分都将共享这个上下文 容器将 转换为键值对,并交给 servletContext 容器创建 中的

  • javaweb在线支付功能实现代码

    本文实例为大家分享了javaweb在线支付功能的具体实现代码,供大家参考,具体内容如下 package com.learning.web.servlet; import java.io.IOException; import java.util.ResourceBundle; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.Ht

  • javaweb中mysql数据库连接步骤方法及其实例

    一.直接连接,不封装到工具类中,主要步骤: 先导包:mysql-connector-java-5.0.8-bin.jar(点击跳转到下载界面),放在WebRoot/WEB-INF/lib/下 1.加载驱动//com.MySQL.jdbc.Driver 2.获取连接 Connection对象 3.获取用于向数据库发送SQL的Statement对象 4.执行sql,获取数据,解析数据 5.关闭连接,释放资源 /*协议:子协议://主机:端口/数据库名*/ Stringurl="jdbc:mysql:

  • 详解velocity模板使javaWeb的html+js实现模块化

    详解velocity模板使javaWeb的html+js实现模块化 页面上一些基础数据或者其他页面经常用到部分,可以独立出来做成小组件,组件预留调用入口,需要的页面直接调用即可. 如图,页面中的展示分类和搜索标签在多个页面重复使用,可以将这部分内容独立出来,做成组件,供后续开发调用: classify_search_tag.html文件如下,其中包含HTML节点和jQuery代码: <!-- 展示分类与搜索标签组件使用说明: 1.新增时父页面调用方法:页面加载时调用 goodsClassifyA

  • JavaWeb 文件的上传和下载功能简单实现代码

    一.文件的上传和下载 1.文件上传的原理分析 1.文件上传的必要前提: a.提供form表单,method必须是post           b.form表单的enctype必须是multipart/form-data           c.提供input type="file"类的上传输入域 2.enctype属性 作用:告知服务器请求正文的MIME类型(请求消息头:Content-Type作用是一致的)      可选值: application/x-www-form-urlen

随机推荐