Ajax+Java实现大文件切割上传
技术体系:html5(formdata) + java + servlet3.0+maven + tomcat7
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>大文件切割上传</title>
<style>
#wrap{width:600px; height:400px; border:1px solid #ccc; margin:10px auto;} </style>
</head>
<body>
<p>文件上传:<input type="file" id="file" onchange="uploadFile(this);"></p>
</body>
</html>
<script>
function uploadFile(file){
var File = file.files[0];
var totalSize = File.size; //文件总大小
var splitSize = 10 * 1024 * 1024; //10M 切割文件大小
var len = Math.ceil(totalSize/splitSize);
var fileName = File.name;
var xhr = new XMLHttpRequest();
var isLast = false;
var step = Math.ceil(100/len);
for(var i = 0 ; i< len;i++){
blob = File.slice(i*splitSize,splitSize*(i+1));
isLast = (i == len-1) ? true:false;
var result = upload(blob,i);
console.log("上传结果:" + result);
} function upload(blob,index){
var formData = new FormData();
formData.append("index",index);
formData.append("fileName",fileName);
formData.append("isLast",isLast);
formData.append("splitSize",splitSize);
formData.append("file",blob);
xhr.open("POST", "ajax4.do",false);
xhr.send(formData);
return xhr.responseText;
} } </script>
后台代码:
package com.sgepit.ajax; import java.io.IOException; import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part; @WebServlet("/ajax4.do")
@MultipartConfig
public class Ajax4 extends HttpServlet { final String uploadPath = "D:/uploadFile/"; @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String index = req.getParameter("index");
String fileName = req.getParameter("fileName");
String isLast = req.getParameter("isLast");
String splitSize = req.getParameter("splitSize");
splitSize = null == splitSize ? "0" : splitSize; int size = Integer.parseInt(splitSize); Part part = req.getPart("file");
try {
if(null != part && part.getSize() != 0){
StringBuffer sbRealPath = new StringBuffer();
sbRealPath.append(uploadPath).append(index).append(".").append("part");
//写入文件
part.write(sbRealPath.toString());
if("true".equals(isLast)){ //如果是最后一次加载,准备合并文件
FileUtil fileUtil = new FileUtil();
fileUtil.mergePartFiles(uploadPath, ".part", size, uploadPath+fileName);
Thread.sleep(3000); //睡眠3秒以后再删除
fileUtil.deleteSplitFiles(uploadPath,".part");
}
resp.getWriter().write("success");
}
} catch (Exception e) {
e.printStackTrace();
} } }
工具方法:
package com.sgepit.ajax; import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; /**
* 文件处理辅助类
*
*/
public class FileUtil { /**
* 获取指定目录下特定文件后缀名的文件列表(不包括子文件夹)
* @param dirPath 目录路径
* @param suffix 文件后缀
* @return
*/
public static ArrayList<File> getDirFiles(String dirPath,final String suffix) {
File path = new File(dirPath);
File[] fileArr = path.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
String lowerName = name.toLowerCase();
String lowerSuffix = suffix.toLowerCase();
if (lowerName.endsWith(lowerSuffix)) {
return true;
}
return false;
} });
ArrayList<File> files = new ArrayList<File>(); for (File f : fileArr) {
if (f.isFile()) {
files.add(f);
}
}
return files;
} /**
* 合并文件
*
* @param dirPath 上传文件所在的目录名称
* @param partFileSuffix 拆分文件后缀名
* @param partFileSize拆分文件的字节数大小
* @param mergeFileName 合并后的文件名
* @throws IOException
*/
public void mergePartFiles(String dirPath, String partFileSuffix,
int partFileSize, String mergeFileName) throws IOException {
ArrayList<File> partFiles = FileUtil.getDirFiles(dirPath, partFileSuffix);
Collections.sort(partFiles, new FileComparator()); RandomAccessFile randomAccessFile = new RandomAccessFile(mergeFileName,"rw");
randomAccessFile.setLength(partFileSize * (partFiles.size() - 1)
+ partFiles.get(partFiles.size() - 1).length());
randomAccessFile.close(); ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
partFiles.size(), partFiles.size() * 3, 1, TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(partFiles.size() * 2)); for (int i = 0; i < partFiles.size(); i++) {
threadPool.execute(new MergeRunnable(i * partFileSize,mergeFileName, partFiles.get(i)));
}
} /**删除临时文件
* @param dirPath
* @param partFileSuffix
*/
public void deleteSplitFiles(String dirPath,String partFileSuffix){
ArrayList<File> partFiles = FileUtil.getDirFiles(dirPath, partFileSuffix);
for (int i = 0; i < partFiles.size(); i++) {
partFiles.get(i).delete();
} } /**
* 根据文件名,比较文件 ,根据文件名排序
*/
private class FileComparator implements Comparator<File> {
public int compare(File o1, File o2) {
return o1.getName().compareToIgnoreCase(o2.getName());
}
} /**
* 合并处理Runnable
*
*/
private class MergeRunnable implements Runnable {
long startPos;
String mergeFileName;
File partFile; public MergeRunnable(long startPos, String mergeFileName, File partFile) {
this.startPos = startPos;
this.mergeFileName = mergeFileName;
this.partFile = partFile;
} public void run() {
RandomAccessFile rFile;
try {
rFile = new RandomAccessFile(mergeFileName, "rw");
rFile.seek(startPos);
FileInputStream fs = new FileInputStream(partFile);
byte[] b = new byte[fs.available()];
fs.read(b);
fs.close();
rFile.write(b);
rFile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} }
备注:一定要注意,在maven环境下,启动tomcat的时候,一定要用tomcat7:run, 而不是tomcat:run,否则无法正常使用。(踩坑了)
Ajax+Java实现大文件切割上传的更多相关文章
- java springboot 大文件分片上传处理
参考自:https://blog.csdn.net/u014150463/article/details/74044467 这里只写后端的代码,基本的思想就是,前端将文件分片,然后每次访问上传接口的时 ...
- 支持IE低版本的上传 大文件切割上传 断点续传 秒传
1. http://files.cnblogs.com/files/blackice/UploadDemo.rar 此demo是使用的 swfupload 2.http://download.csdn ...
- AJAX-----16HTML5实现大文件切割上传
2点多接了个电话导致失眠,没办法,跑起来接着板砖了...... 废话不多说,直接走码... <!DOCTYPE html> <html lang="en"> ...
- java http大文件断点续传上传
因为需要研究下断点上传的问题.找了很久终于找到一个比较好的项目. 效果: 上传中,显示进度,时间,百分比. 点击[Pause]暂停,点击[Resume]继续. 2,代码分析 项目进行了封装使用最简单的 ...
- AJAX大文件切割上传以及带进度条。
分块传输的原理就是利用HTML5新增的文件slice截取函数. 代码如下: html: <input id="f" type="file" name=&q ...
- vue大文件分片上传插件
最近遇见一个需要上传百兆大文件的需求,调研了七牛和腾讯云的切片分段上传功能,因此在此整理前端大文件上传相关功能的实现. 在某些业务中,大文件上传是一个比较重要的交互场景,如上传入库比较大的Excel表 ...
- Hadoop如何将TB级大文件的上传性能优化上百倍?
这篇文章,我们来看看,Hadoop的HDFS分布式文件系统的文件上传的性能优化. 首先,我们还是通过一张图来回顾一下文件上传的大概的原理. 由上图所示,文件上传的原理,其实说出来也简单. 比如有个TB ...
- 利用blob对象实现大文件分片上传
首先说分片上传,我们在进行文件上传的时候,因为服务器的限制,会限制每一次上传到服务器的文件大小不会很大,这个时候我们就需要把一个需要上传的文件进行切割,然后分别进行上传到服务器. 假如需要做到这一步, ...
- js实现大文件分片上传的方法
借助js的Blob对象FormData对象可以实现大文件分片上传的功能,关于Blob和FormData的具体使用方法可以到如下地址去查看FormData 对象的使用Blob 对象的使用以下是实现代码, ...
随机推荐
- Hadoop2.6.5高可用集群搭建
软件环境: linux系统: CentOS6.7 Hadoop版本: 2.6.5 zookeeper版本: 3.4.8 主机配置: 一共m1, m2, m3, m4, m5这五部机, 每部主机的用户名 ...
- windows server 2012 r2 安装无法找到install.wim 错误代码0x80070026,以及制作U启动盘决解ISO文件超过5G大小限制的解决方案(转)
戴尔服务器r530 windows server 2012 r2 安装无法找到install.wim 错误代码0x80070026,以及制作U启动盘决解ISO文件超过5G大小限制的解决方案 关于在服务 ...
- (转)Openlayers 2.X加载天地图
http://blog.csdn.net/gisshixisheng/article/details/44621923 概述: 在前面的章节,讲到了Arcgis for js加载天地图,在本节讲述如何 ...
- html 底部虚线
<div style="width: 100%; font-size: 14px; color: #666; border-bottom: 1px dashed #666;" ...
- vue点击实现 路由的跳转
点击按钮实现路由的跳转 <div @click="gotoMenu">按钮</div> 实现跳转 methods: { gotoMenu(){ //跳转到上 ...
- 【JavaScript游戏开发】使用HTML5+Canvas+JavaScript 封装的一个超级马里奥游戏(包含源码)
这个游戏基本上是建立在JavaScript模块化的开发基础上进行封装的,对游戏里面需要使用到的游戏场景进行了封装,分别实现了Game,Sprite,enemy,player, base,Animati ...
- TFS代码迁移Git
描述 将TFS上的代码迁移到Git做版本控制. 参考地址 tfs-git下载:https://github.com/git-tfs/git-tfs/releases chocolatey安装:http ...
- 单例模式的理解【php】
单例模式(Singleton Pattern):顾名思义,就是只有一个实例.作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例. 为什么要使用单例模式 1.P ...
- jQuery cxCalendar 日期选择器
简介 cxCalendar 是基于 jQuery 的日期选择器插件. 它灵活自由,你可以自定义外观,日期的范围,返回的格式等. 版本: jQuery v1.7+ jQuery cxCalendar v ...
- display显示属性理解
display属性设置一个元素应如何显示,是我们在前端开发中常常使用的一个属性,其中,最常见的有: 目录 display:none;表示此元素将不被显示. display:block;将元素显示为块元 ...