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 对象的使用以下是实现代码, ...
随机推荐
- 编译Caffe-Win错误集锦
Caffe在Windows下编译还是遇到不少麻烦的... 1.visual studio 2013 error C2371: 'int8_t' : redefinition; 引入的unistd.h文 ...
- POJ_3020_最小路径覆盖
Antenna Placement Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8721 Accepted: 4330 ...
- The as! Operator
Prior to Swift 1.2, the as operator could be used to carry out two different kinds of conversion, de ...
- 【转载】JSTL和EL的使用
使用JSTL前的准备 想要使用JSTL,首先需要给工程导入JSTL的包(JSTL.jar和standard.jar). JSTL标签库 在JSTL中分为以下五个标签 核心标签 格式化标签 SQL标签 ...
- python学习之小小爬虫
学习python一段时间了,写了一个图片的小小爬虫,分享下,不喜勿喷! #coding=utf-8 ''' Created on 2015-5-22 @author: 悦文 ''' import re ...
- Linux基础:uniq命令总结
本文只总结一些常用的用法,更详细的说明见man uniq和 uniq --help. uniq命令 uniq命令主要用于去重. 需要注意的是,不相邻的行不算重复值. 语法格式 Usage: uniq ...
- 通过JDBC取Oracle数据库的时间字段时,时间丢失,只剩日期
通过JDBC连接Oracle数据库,在查询的时候发现时间字段取出来值后只剩下了日期,时间消失了.查资料发现跟Oracle jdbc驱动版本有关,这里先贴出解决方案: 修改数据库的连接方式: try { ...
- vue 手机键盘把底部按钮顶上去
背景:在写提交订单页面时候,底部按钮当我点击输入留言信息的时候,底部提交订单按钮被输入法软键盘顶上去遮挡住了. h5 ios输入框与键盘 兼容性优化 实现原理:当页面高度发生变化的时候改变底部butt ...
- 使用pm2启动nodejs+express+mysql管理系统步骤
背景: 由于个人兴趣,了解了一下nodejs+express+mysql项目.在项目搭建完成并开发完成并部署时,遇到一个尴尬的问题,就是后台的servive服务启动问题.日常开发时,打开2个cm窗口, ...
- 什么是hashMap,初始长度,高并发死锁,java8 hashMap做的性能提升
问题1:HashM安排的初始长度,为什么? 初始长度是 16,每次扩展或者是手动初始化,长度必须是 2的幂. 因为: index = HashCode(Key) & (length - 1), ...