溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

在Java項目中使用WebUploader如何實現(xiàn)一個文件上傳功能

發(fā)布時間:2020-11-12 16:24:36 來源:億速云 閱讀:157 作者:Leah 欄目:編程語言

本篇文章為大家展示了在Java項目中使用WebUploader如何實現(xiàn)一個文件上傳功能,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細(xì)介紹希望你能有所收獲。

之前自己寫小項目的時候也碰到過文件上傳的問題,沒有找到很好的解決方案。雖然之前網(wǎng)找各種解決方案的時候也看到過WebUploader,但沒有進一步深究。這次稍微深入了解了些,這里也做個小結(jié)。

簡單的文件和普通數(shù)據(jù)上傳并保存

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.創(chuàng)建DiskFileItemFactory對象,配置緩存用
  DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
  // 2. 創(chuàng)建 ServletFileUpload對象
  ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);
  // 3. 設(shè)置文件名稱編碼
  servletFileUpload.setHeaderEncoding("utf-8");
  // 4. 開始解析文件
  try {
   List<FileItem> items = servletFileUpload.parseRequest(request);
   for (FileItem fileItem : items) {
    if (fileItem.isFormField()) { // >> 普通數(shù)據(jù)
     String info = fileItem.getString("utf-8");
     System.out.println("info:" + info);
    } else { // >> 文件
     // 1. 獲取文件名稱
     String name = fileItem.getName();
     // 2. 獲取文件的實際內(nèi)容
     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組件上傳

分片、并發(fā),預(yù)覽、壓縮,多途徑添加文件夾(文件多選,拖拽等),妙傳

頁面樣式使用

<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.創(chuàng)建頁面元素 -->
 <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>無法預(yù)覽&nbsp;</span>");
   } else {
    $("#" + file.id).find("img").attr("src", src);
   }
  });
 }
);
// 監(jiān)控上傳進度
// percentage:代表上傳文件的百分比
uploader.on("uploadProgress", function(file, percentage) {
 $("#" + file.id).find("span.percentage").text(Math.round(percentage * 100) + "%");
});
  • 拖拽上傳、粘貼上傳
  • 創(chuàng)建拖拽區(qū)域并設(shè)置樣式:
<style type="text/css">
 #dndArea {
  width: 200px;
  height: 100px;
  border-color: red;
  border-style: dashed;
 }
</style>  
<!-- 創(chuàng)建用于拖拽的區(qū)域 -->
<div id="dndArea"></div>
  • 基本配置中增加dnd區(qū)域配置(開啟拖拽)

屏蔽拖拽區(qū)域外的響應(yīng)

開啟粘貼功能

var uploader = WebUploader.create(
 {  swf:"${pageContext.request.contextPath }/js/Uploader.swf",
server:"${pageContext.request.contextPath }/FileUploadServlet",
  pick:"#filePicker",
  auto:true,
  // 開啟拖拽
  dnd:"#dndArea",
  // 屏蔽拖拽區(qū)域外的響應(yīng)
  disableGlobalDnd:true,
  // 
 }  
);
  • 文件的分塊上傳

前端根據(jù)需要發(fā)送的文件生成一個md5字符串發(fā)送給后臺,后臺創(chuàng)建以該md5字符串命名的文件夾。前端分塊發(fā)送文件并發(fā)送文件塊序號給后臺,后臺接收到文件后按序號名稱保存。前端發(fā)送完成后通知后臺合并文件。

  • 前端配置,開啟是否分塊、分塊大小、線程個數(shù)等
// 上傳基本配置
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",

 // 分塊上傳設(shè)置
 // 是否分塊
 chunked:true,
 // 每塊文件大?。J(rèn)5M)
 chunkSize:5*1024*1024,
 // 開啟幾個并非線程(默認(rèn)3個)
 threads:3,
 // 在上傳當(dāng)前文件時,準(zhǔn)備好下一個文件
 prepareNextFile:true
}  
);
  • 前端監(jiān)聽分塊

可以分為三個時間點:

  • before-send-file: 該方法在文件上傳前調(diào)用(只會在一個文件上傳前調(diào)用)。

可以在該方法中獲取文件的md5字符串作為后臺保存分塊文件的目錄名

  • before-send: 該方法在每個分塊文件上傳前調(diào)用(每個分塊上傳前都會調(diào)用)。

可以在該方法中發(fā)送md5字符串到后臺,后臺判斷是否已經(jīng)存在分塊決定是否發(fā)送以達到斷點續(xù)傳的功能

  • after-send-file: 該方法在所有文件上傳完成沒有錯誤之后調(diào)用(所有分塊上傳完成后調(diào)用)。

可以在該方法中通知后臺合并所有分塊

  • 前端獲取文件md5字符串,發(fā)送每個分塊時發(fā)送到后臺,后臺接收如果不存在文件夾創(chuàng)建文件夾,保存分塊發(fā)送的文件
 // 監(jiān)聽分塊上傳的時間點,斷點續(xù)傳
var fileMd5;
WebUploader.Uploader.register({
 "before-send-file":"beforeSendFile",
 "before-send":"beforeSend",
 "after-send-file":"afterSendFile"
 },{
  beforeSendFile:function(file) {
   // 創(chuàng)建一個deffered,用于通知是否完成操作
   var deferred = WebUploader.Deferred();
   // 計算文件的唯一標(biāo)識,用于斷點續(xù)傳和妙傳
   (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();
   // 發(fā)送文件md5字符串到后臺
   this.owner.options.formData.fileMd5 = fileMd5;
   deferred.resolve();
   return deferred.promise();
  },
  afterSendFile:function() {
  }
 }
);

添加state標(biāo)簽

$("#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()) { // >> 普通數(shù)據(jù)
      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. 獲取文件的實際內(nèi)容
      InputStream is = fileItem.getInputStream();
      // 3. 保存文件
      FileUtils.copyInputStreamToFile(is, new File(serverPath + "/" + name));*/
      // 如果文件夾沒有創(chuàng)建文件夾
      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&#63;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;
        }
      });
      // 轉(zhuǎn)成集合,便于排序
      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");
      // 創(chuàng)建文件
      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();
      }
      // 關(guān)閉流
      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);
  }
}
  • 斷點續(xù)傳

前端頁面發(fā)送前添加校驗,校驗是否已經(jīng)上傳分塊

beforeSend:function(block) {
        var deferred = WebUploader.Deferred();
        // 支持?jǐn)帱c續(xù)傳,發(fā)送到后臺判斷是否已經(jīng)上傳過
        $.ajax(
          {
            type:"POST",
            url:"${pageContext.request.contextPath}/UploadActionServlet&#63;action=checkChunk",
            data:{
              // 文件唯一表示                
              fileMd5:fileMd5,
              // 當(dāng)前分塊下標(biāo)
              chunk:block.chunk,
              // 當(dāng)前分塊大小
              chunkSize:block.end-block.start
            },
            dataType:"json",
            success:function(response) {
              if(response.ifExist) {
                // 分塊存在,跳過該分塊
                deferred.reject();
              } else {
                // 分塊不存在或不完整,重新發(fā)送
                deferred.resolve();
              }
            }
          }
        );
        // 發(fā)送文件md5字符串到后臺
        this.owner.options.formData.fileMd5 = fileMd5;
        return deferred.promise();
      }
  • action中添加校驗
else if ("checkChunk".equals(action)) {
    // 校驗文件是否已經(jīng)上傳并返回結(jié)果給前端
    // 文件唯一表示                
    String fileMd5 = request.getParameter("fileMd5");
    // 當(dāng)前分塊下標(biāo)
    String chunk = request.getParameter("chunk");
    // 當(dāng)前分塊大小
    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}");
    }
  }

上述內(nèi)容就是在Java項目中使用WebUploader如何實現(xiàn)一個文件上傳功能,你們學(xué)到知識或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識儲備,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI