Home  >  Article  >  Java  >  Detailed explanation of the file upload function code using the combination of Java and WebUploader

Detailed explanation of the file upload function code using the combination of Java and WebUploader

黄舟
黄舟Original
2017-03-30 10:11:322394browse

This article mainly introduces Java combined with WebUploader to implement File Upload Function, the code is simple and easy to understand, very good, and has reference value. Friends who need it can refer to it

I also encountered the problem of file uploading when I wrote a small project before, and I didn’t find a good one. Solution. Although I saw WebUploader when I was looking for various solutions online, I didn’t go into it further this time. Here is a summary. Simple file and normal data upload and save

jsp

Page:

<%@ 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);
 }
}

Use WebUploader component to upload

Sharding, concurrency, preview, compression, multiple ways to add folders (multi-select files, drag Drag, etc.), Miaozhuan

page style uses

<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.创建页面元素 -->
 <p id="upload">
  <p id="filePicker">文件上传</p>
 </p>
 <!-- 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>

to generate a file name list, display upload progress in real time, and display

thumbnails
  • ##Add file list p, 19feef058358c9be7d7866ccaedefdd494b3e26ee717c64999d7867364b1b4a3

  • ##Generate thumbnails and display upload progress

    // 生成缩略图和上传进度
    uploader.on("fileQueued", function(file) {
      // 把文件信息追加到fileList的p中
      $("#fileList").append("<p id=&#39;" + file.id + "&#39;><img/><span>" + file.name + "</span><p><span class=&#39;percentage&#39;><span></p></p>")
      // 制作缩略图
      // 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) + "%");
    });
  • Drag and drop upload, paste upload

    Create drag and drop Area and set the style:
  • <style type="text/css">
     #dndArea {
      width: 200px;
      height: 100px;
      border-color: red;
      border-style: dashed;
     }
    </style>  
    <!-- 创建用于拖拽的区域 -->
    <p id="dndArea"></p>
  • Add dnd area configuration in the basic configuration (enable drag and drop)

    Shield drag Response outside the drag area
  • Enable the paste function

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

Blocked upload of files

    Files sent by the front end as needed Generate a
  • md5

    string
  • and send it to the background. The background creates a folder named after the md5 string. The front-end sends the file in chunks and sends the file block serial number to the background. The background receives the file. Then save it according to the serial number name. After the front-end is sent, it will notify the background to merge the files.

##Front-end configuration, whether to enable chunking, chunk size, number of threads, etc.

// 上传基本配置
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
}  
);

  • Front-end monitoring block

can be divided into three time points:
  • before- send-file: This method is called before a file is uploaded (it will only be called before a file is uploaded)

You can get the md5 string of the file as a background save block in this method. Directory name of the file
  • before-send: This method is called before each multi-part file is uploaded (called before each multi-part upload).

You can send the md5 string to the background in this method, and the background will judge whether there is already a block and decide whether to send it to achieve the function of resuming the transmission after the breakpoint
  • after-send-file: This method is called after all files have been uploaded without errors (called after all multi-part uploads have been completed).

You can notify the background to merge all chunks in this method
  • The front-end gets the file md5 string and sends it to when sending each chunk In the background, the background receives and creates a folder if the folder does not exist, and saves the file sent in chunks

 // 监听分块上传的时间点,断点续传
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() {
  }
 }
);

Add state tag
    $("#fileList").append("<p id=&#39;" + file.id + "&#39;>
    <img/>
    <span>" + file.name + "</span>
    <p>
    <span class=&#39;state&#39;>
    </span>
    </p>
    <p>
    <span class=&#39;percentage&#39;>
    </span>
    </p>
    </p>");
  • Save the file

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

The front-end notifies the action to merge files

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

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

Breakpoint resume transmission

Add verification before sending the front-end page to verify whether the chunks have been uploaded
    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();
          }
  • Add verification in 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}");
    }
  }

The above is the detailed content of Detailed explanation of the file upload function code using the combination of Java and WebUploader. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn