前段WebUploader;JavaEE大檔案分片上傳接收
Web大檔案分片上傳
Web環境中大檔案上傳不能再用form表單一次上傳了,這樣效率太低;
我在不斷嘗試SpringMVC環境下分片接受檔案,最終失敗;原因目測是 SpringMVC、Struts框架是不支援HTML5方式上傳的(這類框架只能支援Form表單方式的檔案上傳,或者FLash)
那我們可以使用Servlet和SpringMVC結合整合方式實現大檔案分片上傳;
一、來看看我們的web.xml的配置
很明顯兩個servlet,上面一個配置的是SpringMVC的入口,下面servlet是視訊上傳;
他們倆的url-pattern 不能衝突;
二、先來看看WebUploader 的前端程式碼
以下是程式碼:
<%@ 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>
<base
href="${pageContext.request.scheme}://${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}/" >
<script type="text/javascript" src="webuploader/jquery-1.7.2.js"></script>
<script type="text/javascript" src="webuploader/webuploader.min.js"></script>
<link href="webuploader/webuploader.css" type="css/text" />
</head>
<body>
<h2>Hello World!</h2>
<div id="thelist" class="uploader-list"></div>
<div style="margin: 20px 20px 20px 0;">
<div id="picker" class="form-control-focus">選擇檔案</div>
</div>
<button id="btnSync" type="button" class="btn btn-warning">開始同步</button>
<script>
var uploader = WebUploader.create({
// swf檔案路徑
swf : 'webuploader/Uploader.swf',
// 檔案接收服務端。
server : 'UploadVideoServlet',
// 選擇檔案的按鈕。可選。
// 內部根據當前執行是建立,可能是input元素,也可能是flash.
pick : '#picker',
threads:2,
chunked: true, //分片處理
chunkSize: 5 * 1024 * 1024, //每片5M
threads:1,//上傳併發數。允許同時最大上傳程序數。
// 不壓縮image, 預設如果是jpeg,檔案上傳前會壓縮一把再上傳!
resize : false
});
// 當有檔案被新增進佇列的時候
uploader.on('fileQueued', function(file) {
//alert(123);
$("#thelist").append(
'<div id="' + file.id + '" class="item">'
+ '<h4 class="info">' + file.name + '</h4>'
+ '<p class="state">等待上傳...</p>' + '</div>');
});
uploader.on('uploadSuccess', function(file) {
alert(uploader.options.formData.guid);
alert(Math.ceil(file.size/(5*1024*1024)));
alert(file.name);
$('#' + file.id).find('p.state').text('已上傳');
$.post("UploadSuccessServlet", { "guid": uploader.options.formData.guid,chunks:Math.ceil(file.size/(5*1024*1024)),fileName:file.name},
function(data){
}, "json");
});
uploader.on('uploadError', function(file) {
$('#' + file.id).find('p.state').text('上傳出錯');
});
uploader.on('uploadComplete', function(file) {
$('#' + file.id).find('.progress').fadeOut();
});
$("#btnSync").on('click', function() {
if ($(this).hasClass('disabled')) {
return false;
}
uploader.options.formData.guid = Math.random();
uploader.upload();
});
</script>
</body>
</html>
三、servlet分片獲取
分片就是前段將檔案分成多個,每片都是一個post請求,有多少片就請求多少次servlet;
我們以獲取的guid為檔名 建立臨時資料夾,以chunk(片序號)為檔名來儲存檔案;
以下為程式碼:
package com.airodlcx;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;
/**
* Servlet implementation class UploadVideo
*/
public class UploadVideoServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public UploadVideoServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
response.getWriter().append("Served at: ").append(request.getContextPath());
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String path = request.getSession().getServletContext().getRealPath("/upload");
System.out.println(path);
DiskFileItemFactory factory = new DiskFileItemFactory();
// 2、建立一個檔案上傳解析器
ServletFileUpload upload = new ServletFileUpload(factory);
// 解決上傳檔名的中文亂碼
upload.setHeaderEncoding("UTF-8");
// 3、判斷提交上來的資料是否是上傳表單的資料
if (!ServletFileUpload.isMultipartContent(request)) {
return;
}
// 4、使用ServletFileUpload解析器解析上傳資料,解析結果返回的是一個List<FileItem>集合,每一個FileItem對應一個Form表單的輸入項
List<FileItem> list = null;
try {
list = upload.parseRequest(request);
} catch (FileUploadException e) {
e.printStackTrace();
}
HashMap<String, String> map = new HashMap<String, String>();
System.out.println("-------------------------------------------------------------");
for (FileItem item : list) {
if (item.isFormField()) {
/**
* 表單資料
*/
String name = item.getFieldName();
// 解決普通輸入項的資料的中文亂碼問題
String value = item.getString("UTF-8");
// value = new String(value.getBytes("iso8859-1"),"UTF-8");
System.out.println(name + "=" + value);
map.put(name, value);// 放入map集合
} else {
/**
* 檔案上傳
*/
File fileParent = new File(path + "/" + map.get("guid"));//以guid建立臨時資料夾
System.out.println(fileParent.getPath());
if (!fileParent.exists()) {
fileParent.mkdir();
}
String filename = item.getName();
if (filename == null || filename.trim().equals("")) {
continue;
}
// 注意:不同的瀏覽器提交的檔名是不一樣的,有些瀏覽器提交上來的檔名是帶有路徑的,如:
// c:\a\b\1.txt,而有些只是單純的檔名,如:1.txt
// 處理獲取到的上傳檔案的檔名的路徑部分,只保留檔名部分
filename = filename.substring(filename.lastIndexOf("\\") + 1);
//建立檔案
File file;
if (map.get("chunks") != null) {
file = new File(fileParent, map.get("chunk"));
} else {
file = new File(fileParent, "0");
}
//copy
FileUtils.copyInputStreamToFile(item.getInputStream(), file);
}
}
}
}
四、前端WebUploader上傳完畢觸發uploadSuccess事件
uploader.on('uploadSuccess', function(file) {
alert(uploader.options.formData.guid);
alert(Math.ceil(file.size/(5*1024*1024)));
alert(file.name);
$('#' + file.id).find('p.state').text('已上傳');
$.post("UploadSuccessServlet", { "guid": uploader.options.formData.guid,chunks:Math.ceil(file.size/(5*1024*1024)),fileName:file.name},
function(data){
}, "json");
});
請求servlet去合併之前的guid資料夾下的分片檔案,post請求中的分片數量可以用來校驗,獲取的分片是否正確,也可以前端傳遞md5,後臺校驗;
五、後臺獲取的log
圖:上傳的GUID命名的資料夾
圖:資料夾下的分片檔案
每個分割線包住的地方是一個servlet請求,最後在success 請求的servlet是進行檔案校驗併合並檔案即可;程式碼見下:
六、java檔案合併
程式碼見下:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String path = request.getSession().getServletContext().getRealPath("/upload");
String guid = request.getParameter("guid");
int chunks = Integer.parseInt(request.getParameter("chunks"));
String fileName = request.getParameter("fileName");
System.out.println("start...!guid="+guid+";chunks="+chunks+";fileName="+fileName);
/**
* 進行檔案合併
*/
File file = new File(path+"/"+guid);
/**
* 判斷分片數量是否正確
*/
if(file.list().length != chunks){
return;
}
new File("F://upload"+"/"+guid).mkdir();
/**
* 進行檔案合併
*/
File newFile = new File("F://upload"+"/"+guid+"/"+fileName);
FileOutputStream outputStream = new FileOutputStream(newFile, true);//檔案追加寫入
byte[] byt = new byte[10*1024*1024];
int len;
FileInputStream temp = null;//分片檔案
for(int i = 0 ; i<chunks ; i++){
temp = new FileInputStream(new File(path+"/"+guid+"/"+i));
while((len = temp.read(byt))!=-1){
System.out.println(len);
outputStream.write(byt, 0, len);
}
temp.close();
}
/**
* 當所有追加寫入都寫完 才可以關閉流
*/
outputStream.close();
//temp.close(); 寫錯了 移到for迴圈
System.out.println("success!guid="+guid+";chunks="+chunks+";fileName="+fileName);
}
資料夾以guid命名,資料庫儲存guid的名字,後期資料移動,只需要更改前端顯示的路徑;
在這裡up遇到一個問題,上傳報錯:IOException:磁碟空間不足;然而我上傳的磁碟還有20G;原因是系統盤空間不足;up重灌系統就好了;
注:
1、進度條的顯示就很容易了
引入bootstrap的進度條
<div class="progress">
<div id="progress" class="progress-bar" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width: 0%;">
<span class="sr-only">60% Complete</span>
</div>
</div>
2.新增uploadProgress事件監聽
uploader.on('uploadProgress', function(file,percentage) {
$("#progress").css("width",parseInt(percentage*100)+"%");
});
percentage:當前上傳的進度,小數,數值為1是上傳完畢;
效果如下:
PS:UI簡陋還請見諒!
QQ:346640094 Email:[email protected];
相關推薦
前段WebUploader;JavaEE大檔案分片上傳接收
Web大檔案分片上傳 Web環境中大檔案上傳不能再用form表單一次上傳了,這樣效率太低; 我在不斷嘗試SpringMVC環境下分片接受檔案,最終失敗;原因目測是 SpringMVC、Struts框架是不支援HTML5方式上傳的(這類框架只能支援Form表單
webuploader在springMVC+jquery+Java開發環境下的大檔案分片上傳
參考的文章http://blog.csdn.net/new_sara/article/details/51604997 因為從網上看到的總是和自己專案開發有些許差別,所以也是在除錯了很久之後,發現適合自己專案的程式碼,現在把過程記錄下來,以便以後查閱. 注意: 1,web
在瀏覽器進行大檔案分片上傳(java服務端實現)
最近在做web網盤的系統,網盤最基本的功能便是檔案上傳,但是檔案上傳當遇到大檔案的時候,在web端按傳統方式上傳簡直是災難,所以大檔案上傳可以採用分片上傳的辦法。其主要思路是:1.大檔案上傳時進行分片;2.分片上傳;3.對分片檔案進行合併。 思路比較清晰簡單,但一些問題在於:1.大檔案如何進
PHP大檔案分片上傳的實現方法
一、前言 在網站開發中,經常會有上傳檔案的需求,有的檔案size太大直接上傳,經常會導致上傳過程中耗時太久,大量佔用頻寬資源,因此有了分片上傳。 分片上傳主要是前端將一個較大的檔案分成等分的幾片,標識當前分片是第幾片和總共幾片,待所有的分片均上傳成功的時候,在後臺進行合成檔案即可。 二、
網頁內實現大檔案分片上傳、斷點續傳
最近做公司的專案,需要在後臺控制系統中新增一個功能-------向伺服器傳送程式更新包;這些程式更新包大小不固定,但基本都在1G到4G之間,剛開始還真是難倒我了,因為之前的專案中沒有上傳過這麼大的檔案,還要斷點續傳,後來經過查資料,寫DEMO,這個問題終於解決了; 解決辦法: 使用XMLHt
java springboot 大檔案分片上傳處理
這裡只寫後端的程式碼,基本的思想就是,前端將檔案分片,然後每次訪問上傳介面的時候,向後端傳入引數:當前為第幾塊問價,和分片總數 下面直接貼程式碼吧,一些難懂的我大部分都加上註釋了: 上傳檔案實體類: /** * 檔案傳輸物件 * @ApiModel和@ApiModelProperty及C
eggJS大檔案分片上傳與合併
前臺上傳使用vue+axios 前臺程式碼: // 計算分片總數 for (let i = 0; i < Math.ceil(this.file.size / this.uploadFragment.fragment); i++) { this.uploadFra
php大檔案分片上傳
HTML <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="widt
iOS大檔案分片上傳和斷點續傳
總結一下大檔案分片上傳和斷點續傳的問題。因為檔案過大(比如1G以上),必須要考慮上傳過程網路中斷的情況。http的網路請求中本身就已經具備了分片上傳功能,當傳輸的檔案比較大時,http協議自動會將檔案切片(分塊),但這不是我們現在說的重點,我們要做的事是保證在網路中斷後1G
Android 大檔案分片上傳斷點續傳任務管理實現
Transer 是一個傳輸框架,目前支援: - 支援 HTTP/HTTPS 斷點續傳下載 - 支援 HTTP/HTTPS 大檔案分片上傳 - 支援 類EventBus的task狀態變更通知,支援三種執行緒的訂閱模式 - 支援 任務分組,分使用者
js實現大檔案分片上傳的方法
<input type="file" name="file" id="file"> <button id="upload" onClick="upload()">upload</button>var bytesPerPiece = 1024
Node + js實現大檔案分片上傳基本原理及實踐(一)
閱讀目錄 一:什麼是分片上傳? 二:理解Blob物件中的slice方法對檔案進行分割及其他知識點 三. 使用 spark-md5 生成 md5檔案 四. 使用koa+js實現大檔案分片上傳實踐 回到頂部 一:什麼是分片上傳? 分片上傳是把一個大的檔案分成若干塊,一塊一塊的傳輸。這
nodeJs + js 大檔案分片上傳
簡單的檔案上傳 一、準備檔案上傳的條件: 1、安裝nodejs環境 2、安裝vue環境 3、驗證環境是否安裝成功 二、實現上傳步驟 1、前端部分使用 vue-cli 腳手架,搭建一個 demo 版本,能夠實現簡單互動: <template> <div id="app">
.NET Core Web APi大檔案分片上傳研究
前言 前兩天發表利用FormData進行檔案上傳,然後有人問要是大檔案幾個G上傳怎麼搞,常見的不就是分片再搞下斷點續傳,動動手差不多也能搞出來,只不過要深入的話,考慮的東西還是很多。由於斷點續傳之前寫個幾篇,這裡試試利用FormData來進行分片上傳。 .NET Core Web APi檔案分片上傳 這裡我們
WebUploader-----大檔案列表上傳
大家好 在這裡 給大家介紹一下款適用於大檔案傳輸的外掛--------------------WebUploader 首先呢 我先給出該外掛需要的引數文件 官網地址:http://fex.baidu.com/webuploader
PHP大檔案分割上傳 PHP分片上傳
這篇文章主要為大家詳細介紹了PHP大檔案分割上傳,PHP分片上傳,具有一定的參考價值,感興趣的小夥伴們可以參考一下 服務端為什麼不能直接傳大檔案?跟php.ini裡面的幾個配置有關 upload_max_filesize = 2M //PHP最大能接受的檔案大小 post_max_siz
大文分片上傳 多執行緒上傳檔案(接收端)
package com.controller; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; i
【轉】Android-使用Socket進行大檔案斷點上傳續傳
在Android中上傳檔案可以採用HTTP方式,也可以採用Socket方式,但是HTTP方式不能上傳大檔案,這裡介紹一種通過Socket方式來進行斷點續傳的方式,服務端會記錄下檔案的上傳進度,當某一次上傳過程意外終止後,下一次可以繼續上傳,這裡用到的其實還是J2SE裡的知識。 這個上傳程式的
【效能優化的祕密】Hadoop如何將TB級大檔案的上傳效能優化上百倍
往期文章1、 拜託!面試請不要再問我Spring Cloud底層原理2、 【雙11狂歡的背後】微服務註冊中心如何承載大型系統的千萬級訪問?3、 【效能優化之道】每秒上萬併發下的Spring Cloud引數優化實戰4、 微服務架構如何保障雙11狂歡下的99.99%
【效能優化的祕密】Hadoop如何將TB級大檔案的上傳效能優化上百倍?
一、寫在前面 上一篇文章,我們聊了一下Hadoop中的NameNode裡的edits log寫機制。 主要分析了edits log寫入磁碟和網路的時候,是如何通過分段加鎖以及雙緩衝的機制,大幅度提升了多執行緒併發寫edits log的吞吐量,從而支援高併發的訪問。 如果沒看那