首页 > 开发 > Java > 正文

Java与WebUploader相结合实现文件上传功能(实例代码)

2024-07-13 10:05:56
字体:
来源:转载
供稿:网友

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

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

jsp页面:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title></head><body> <form action="${pageContext.request.contextPath }/FileUploadServlet" method="post" enctype="multipart/form-data">  文件:<input type="file" value="请选择文件" name="file" /> <br/>  信息:<input type="text" name="info" /> <br/>  <input type="submit" value="提交" /> </form></body></html>

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<FileItem> 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组件上传

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

页面样式使用

<html><title>使用webuploader上传</title><!-- 1.引入文件 --><link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath }/js/webuploader.css" rel="external nofollow" ><script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery-2.1.4.min.js"></script><script type="text/javascript" src="${pageContext.request.contextPath }/js/webuploader.js"></script></head><body> <!-- 2.创建页面元素 --> <div id="upload">  <div id="filePicker">文件上传</div> </div> <!-- 3.添加js代码 --> <script type="text/javascript">  var uploader = WebUploader.create(   {    swf:"${pageContext.request.contextPath }/js/Uploader.swf",    server:"${pageContext.request.contextPath }/FileUploadServlet",    pick:"#filePicker",    auto:true   }    ); </script></body></html>
  • 生成文件名列表、实时显示上传进度、显示缩略图
  • 增加文件列表div, <div id="fileList"></div>
  • 生成缩略图和显示上传进度
// 生成缩略图和上传进度uploader.on("fileQueued", function(file) {  // 把文件信息追加到fileList的div中  $("#fileList").append("<div id='" + file.id + "'><img/><span>" + file.name + "</span><div><span class='percentage'><span></div></div>")  // 制作缩略图  // error:不是图片,则有error  // src:代表生成缩略图的地址  uploader.makeThumb(file, function(error, src) {   if (error) {    $("#" + file.id).find("img").replaceWith("<span>无法预览 </span>");   } 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) + "%");});
  • 拖拽上传、粘贴上传
  • 创建拖拽区域并设置样式:
<style type="text/css"> #dndArea {  width: 200px;  height: 100px;  border-color: red;  border-style: dashed; }</style>  <!-- 创建用于拖拽的区域 --><div id="dndArea"></div>
  • 基本配置中增加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("<div id='" + file.id + "'><img/><span>" + file.name + "</span><div><span class='state'></span></div><div><span class='percentage'></span></div></div>");

保存文件

// 4. 开始解析文件// 文件md5获取的字符串String fileMd5 = null;// 文件的索引String chunk = null;try {  List<FileItem> 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<File> fileList = new ArrayList<File>(Arrays.asList(fileArray));      // 从小到大排序      Collections.sort(fileList, new Comparator<File>() {        @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}");    }  }

以上所述是小编给大家介绍的Java与WebUploader相结合实现文件上传功能(实例代码),希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对VeVb武林网网站的支持!


注:相关教程知识阅读请移步到JAVA教程频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表