博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java结合WebUploader文件上传
阅读量:5846 次
发布时间:2019-06-18

本文共 12989 字,大约阅读时间需要 43 分钟。

        之前自己写小项目的时候也碰到过文件上传的问题,没有找到很好的解决方案。虽然之前网找各种解决方案的时候也看到过WebUploader,但没有进一步深究。这次稍微深入了解了些,这里也做个小结。

简单的文件和普通数据上传并保存

 JSP页面:

 

<%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%>
Insert title here
文件:
信息:

 servlet:

package com.yihengliu.web.action;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.util.List;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.commons.fileupload.FileItem;import org.apache.commons.fileupload.disk.DiskFileItemFactory;import org.apache.commons.fileupload.servlet.ServletFileUpload;import org.apache.commons.io.FileUtils;/** * Servlet user to accept file upload */public class FileUploadServlet extends HttpServlet {    private static final long serialVersionUID = 1L;    private String serverPath = "e:/";    protected void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        response.getWriter().append("Served at: ").append(request.getContextPath());        System.out.println("进入后台...");        // 1.创建DiskFileItemFactory对象,配置缓存用        DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();        // 2. 创建 ServletFileUpload对象        ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);        // 3. 设置文件名称编码        servletFileUpload.setHeaderEncoding("utf-8");        // 4. 开始解析文件        try {            List
items = servletFileUpload.parseRequest(request); for (FileItem fileItem : items) { if (fileItem.isFormField()) { // >> 普通数据 String info = fileItem.getString("utf-8"); System.out.println("info:" + info); } else { // >> 文件 // 1. 获取文件名称 String name = fileItem.getName(); // 2. 获取文件的实际内容 InputStream is = fileItem.getInputStream(); // 3. 保存文件 FileUtils.copyInputStreamToFile(is, new File(serverPath + "/" + name)); } } } catch (Exception e) { e.printStackTrace(); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }}

 使用WebUploader组件上传

      分片、并发,预览、压缩,多途径添加文件夹(文件多选,拖拽等),妙传

  • 页面样式使用

  

使用webuploader上传
文件上传
  • 生成文件名列表、实时显示上传进度、显示缩略图
  • 增加文件列表div, <div id="fileList"></div>

生成缩略图和显示上传进度

// 生成缩略图和上传进度uploader.on("fileQueued", function(file) {        // 把文件信息追加到fileList的div中        $("#fileList").append("
" + file.name + "
") // 制作缩略图 // error:不是图片,则有error // src:代表生成缩略图的地址 uploader.makeThumb(file, function(error, src) { if (error) { $("#" + file.id).find("img").replaceWith("无法预览 "); } else { $("#" + file.id).find("img").attr("src", src); } }); });// 监控上传进度// percentage:代表上传文件的百分比uploader.on("uploadProgress", function(file, percentage) { $("#" + file.id).find("span.percentage").text(Math.round(percentage * 100) + "%");});
  • 拖拽上传、粘贴上传

 

 

                  创建拖拽区域并设置样式:

        
  • 基本配置中增加dnd区域配置(开启拖拽)

  屏蔽拖拽区域外的响应

  开启粘贴功能

  

var uploader = WebUploader.create(    {        swf:"${pageContext.request.contextPath }/js/Uploader.swf",server:"${pageContext.request.contextPath }/FileUploadServlet",        pick:"#filePicker",        auto:true,        // 开启拖拽        dnd:"#dndArea",        // 屏蔽拖拽区域外的响应        disableGlobalDnd:true,        //     }       );
  • 文件的分块上传

前端根据需要发送的文件生成一个md5字符串发送给后台,后台创建以该md5字符串命名的文件夹。前端分块发送文件并发送文件块序号给后台,后台接收到文件后按序号名称保存。前端发送完成后通知后台合并文件。

前端配置,开启是否分块、分块大小、线程个数等

// 上传基本配置var uploader = WebUploader.create({    swf:"${pageContext.request.contextPath }/js/Uploader.swf",    server:"${pageContext.request.contextPath }/FileUploadServlet",    pick:"#filePicker",    auto:true,    dnd:"#dndArea",    disableGlobalDnd:true,    paste:"#uploader",    // 分块上传设置    // 是否分块    chunked:true,    // 每块文件大小(默认5M)    chunkSize:5*1024*1024,    // 开启几个并非线程(默认3个)    threads:3,    // 在上传当前文件时,准备好下一个文件    prepareNextFile:true}       );
  • 前端监听分块

可以分为三个时间点:

    • before-send-file: 该方法在文件上传前调用(只会在一个文件上传前调用)。
      可以在该方法中获取文件的md5字符串作为后台保存分块文件的目录名
    • before-send: 该方法在每个分块文件上传前调用(每个分块上传前都会调用)。
      可以在该方法中发送md5字符串到后台,后台判断是否已经存在分块决定是否发送以达到断点续传的功能
    • after-send-file: 该方法在所有文件上传完成没有错误之后调用(所有分块上传完成后调用)。
      可以在该方法中通知后台合并所有分块
  • 前端获取文件md5字符串,发送每个分块时发送到后台,后台接收如果不存在文件夹创建文件夹,保存分块发送的文件
// 监听分块上传的时间点,断点续传var fileMd5;WebUploader.Uploader.register({    "before-send-file":"beforeSendFile",    "before-send":"beforeSend",    "after-send-file":"afterSendFile"    },{        beforeSendFile:function(file) {            // 创建一个deffered,用于通知是否完成操作            var deferred = WebUploader.Deferred();            // 计算文件的唯一标识,用于断点续传和妙传            (new WebUploader.Uploader()).md5File(file, 0, 5*1024*1024)                .progress(function(percentage){                    $("#"+file.id).find("span.state").text("正在获取文件信息...");                })                .then(function(val) {                    fileMd5 = val;                    $("#" + file.id).find("span.state").text("成功获取文件信息");                    // 放行                    deferred.resolve();                });            // 通知完成操作            return deferred.promise();        },        beforeSend:function() {            var deferred = WebUploader.Deferred();            // 发送文件md5字符串到后台            this.owner.options.formData.fileMd5 = fileMd5;            deferred.resolve();            return deferred.promise();        },        afterSendFile:function() {        }    });

添加state标签

$("#fileList").append("
" + file.name + "
");

保存文件

// 4. 开始解析文件// 文件md5获取的字符串String fileMd5 = null;// 文件的索引String chunk = null;try {    List
items = servletFileUpload.parseRequest(request); for (FileItem fileItem : items) { if (fileItem.isFormField()) { // >> 普通数据 String fieldName = fileItem.getFieldName(); if ("info".equals(fieldName)) { String info = fileItem.getString("utf-8"); System.out.println("info:" + info); } if ("fileMd5".equals(fieldName)) { fileMd5 = fileItem.getString("utf-8"); System.out.println("fileMd5:" + fileMd5); } if ("chunk".equals(fieldName)) { chunk = fileItem.getString("utf-8"); System.out.println("chunk:" + chunk); } } else { // >> 文件 /*// 1. 获取文件名称 String name = fileItem.getName(); // 2. 获取文件的实际内容 InputStream is = fileItem.getInputStream(); // 3. 保存文件 FileUtils.copyInputStreamToFile(is, new File(serverPath + "/" + name));*/ // 如果文件夹没有创建文件夹 File file = new File(serverPath + "/" + fileMd5); if (!file.exists()) { file.mkdirs(); } // 保存文件 File chunkFile = new File(serverPath + "/" + fileMd5 + "/" + chunk); FileUtils.copyInputStreamToFile(fileItem.getInputStream(), chunkFile); } }
  • 前端通知action进行合并文件

    前端增加:

// 通知合并分块$.ajax(    {        type:"POST",        url:"${pageContext.request.contextPath}/UploadActionServlet?action=mergeChunks",        data:{            fileMd5:fileMd5        },        success:function(response){        }    });

新增合并action:

package com.yihengliu.web.action;import java.io.File;import java.io.FileFilter;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.nio.channels.FileChannel;import java.util.ArrayList;import java.util.Arrays;import java.util.Collections;import java.util.Comparator;import java.util.List;import java.util.UUID;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/** * 合并上传文件 */public class UploadActionServlet extends HttpServlet {    private static final long serialVersionUID = 1L;    private String serverPath = "e:/";    protected void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        System.out.println("进入合并后台...");        String action = request.getParameter("action");        if ("mergeChunks".equals(action)) {            // 获得需要合并的目录            String fileMd5 = request.getParameter("fileMd5");            // 读取目录所有文件            File f = new File(serverPath + "/" + fileMd5);            File[] fileArray = f.listFiles(new FileFilter() {                // 排除目录,只要文件                @Override                public boolean accept(File pathname) {                    if (pathname.isDirectory()) {                        return false;                    }                    return true;                }            });            // 转成集合,便于排序            List
fileList = new ArrayList
(Arrays.asList(fileArray)); // 从小到大排序 Collections.sort(fileList, new Comparator
() { @Override public int compare(File o1, File o2) { if (Integer.parseInt(o1.getName()) < Integer.parseInt(o2.getName())) { return -1; } return 1; } }); // 新建保存文件 File outputFile = new File(serverPath + "/" + UUID.randomUUID().toString() + ".zip"); // 创建文件 outputFile.createNewFile(); // 输出流 FileOutputStream fileOutputStream = new FileOutputStream(outputFile); FileChannel outChannel = fileOutputStream.getChannel(); // 合并 FileChannel inChannel; for (File file : fileList) { inChannel = new FileInputStream(file).getChannel(); inChannel.transferTo(0, inChannel.size(), outChannel); inChannel.close(); // 删除分片 file.delete(); } // 关闭流 fileOutputStream.close(); outChannel.close(); // 清除文件加 File tempFile = new File(serverPath + "/" + fileMd5); if (tempFile.isDirectory() && tempFile.exists()) { tempFile.delete(); } System.out.println("合并文件成功"); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }}
  • 断点续传
    • 前端页面发送前添加校验,校验是否已经上传分块
      beforeSend:function(block) {                var deferred = WebUploader.Deferred();                // 支持断点续传,发送到后台判断是否已经上传过                $.ajax(                    {                        type:"POST",                        url:"${pageContext.request.contextPath}/UploadActionServlet?action=checkChunk",                        data:{                            // 文件唯一表示                                                           fileMd5:fileMd5,                            // 当前分块下标                            chunk:block.chunk,                            // 当前分块大小                            chunkSize:block.end-block.start                        },                        dataType:"json",                        success:function(response) {                            if(response.ifExist) {                                // 分块存在,跳过该分块                                deferred.reject();                            } else {                                // 分块不存在或不完整,重新发送                                deferred.resolve();                            }                        }                    }                );                // 发送文件md5字符串到后台                this.owner.options.formData.fileMd5 = fileMd5;                return deferred.promise();            }
  • action中添加校验
else if ("checkChunk".equals(action)) {        // 校验文件是否已经上传并返回结果给前端        // 文件唯一表示                                       String fileMd5 = request.getParameter("fileMd5");        // 当前分块下标        String chunk = request.getParameter("chunk");        // 当前分块大小        String chunkSize = request.getParameter("chunkSize");        // 找到分块文件        File checkFile = new File(serverPath + "/" + fileMd5 + "/" + chunk);        // 检查文件是否存在,且大小一致        response.setContentType("text/html;charset=utf-8");        if (checkFile.exists() && checkFile.length() == Integer.parseInt((chunkSize))) {            response.getWriter().write("{\"ifExist\":1}");        } else {            response.getWriter().write("{\"ifExist\":0}");        }    }

 

转载于:https://www.cnblogs.com/dongyu666/p/7636911.html

你可能感兴趣的文章
IE6的height小BUG
查看>>
说说IUnitOfWork~DbContext对象的创建应该向BLL层公开
查看>>
强制卸载kernel
查看>>
js 杂项(一)函数篇
查看>>
pythonGUI-wxpython
查看>>
最小生成树模板 加 例题分析 (最小生成树类型汇总)
查看>>
web渗透测试中WAF绕过讲解(二)基于HTTP协议绕过
查看>>
【CSON原创】CSS的障眼法:利用border实现图片的翻转
查看>>
oracle:plsql学习总结(oracle database 10g sql 开发指南)
查看>>
〔转〕Word域的应用和详解2_等式和公式域
查看>>
FZU 1502 Letter Deletion
查看>>
寄存器是什么 有什么作用
查看>>
转载 《Python爬虫学习系列教程》学习笔记
查看>>
NGUI的输入框制作(attach- input filed script的使用)
查看>>
[异常笔记] zookeeper集群启动异常: Cannot open channel to 2 at election address ……
查看>>
mysql 03
查看>>
NgDL:第三周:浅层NN
查看>>
OpenCV基于傅里叶变换进行文本的旋转校正
查看>>
Centreon 安装部署指南
查看>>
项目管理修炼之道之规划项目
查看>>