本文介绍了webuploader分片上传的实现代码(前后端分离),分享给大家,具体如下:
WebUploader是由Baidu WebFE(FEX)团队开发的一个简单的以HTML5为主,FLASH为辅的现代文件上传组件。在现代的浏览器里面能充分发挥HTML5的优势,同时又不摒弃主流IE浏览器,沿用原来的FLASH运行时,兼容IE6+,iOS 6+,android 4+。两套运行时,同样的调用方式,可供用户任意选用。采用大文件分片并发上传,极大的提高了文件上传效率。(这个是从官网上直接copy的解释)
功能描述
1、webuploader是百度研发的上传组件,文档不是特别规整,但是也够用了。
2、前端使用官网的上传图片demo,在此基础上代码略微调整做分片。既可以上传图片也可以上传文件。文件超过分片大小才启用分片。
3、分片上传已做md5校验,达到秒传的效果。分片以后需要合并,可以先分片后合并,也可以边分片边合并,本示例采用的是边分片边合并的方案。
4、后端用springboot做框架搭建。springMVC做rest服务,开启跨域访问。
5、容器用springboot内置的tomcat插件,运行Application的main方法即可启动服务;
关键代码前端
// 实例化
uploader = WebUploader.create({
pick: {
id: '#filePicker',label: '点击选择<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>'
},formData: {
uid: 123
},dnd: '#dndArea',//指定<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>拖拽的区域
paste: '#uploader',//指定监听paste事件的容器,如果不指定,不启用此<a href="https://www.jb51.cc/tag/gongneng/" target="_blank" class="keywords">功能</a>。此<a href="https://www.jb51.cc/tag/gongneng/" target="_blank" class="keywords">功能</a>为通过粘贴来<a href="https://www.jb51.cc/tag/tianjia/" target="_blank" class="keywords">添加</a>截屏的<a href="https://www.jb51.cc/tag/tupian/" target="_blank" class="keywords">图片</a>。建议设置为document.body.
swf: '../plugins/webuploader/Uploader.swf',chunked: true,chunkSize: chunkSize,chunkRetry: false,threads: 1,server: uploadUrl,// runtimeOrder: 'flash',// accept: {
// title: 'Images',// extensions: 'gif,jpg,jpeg,bmp,png',// mimeTypes: 'image/*'
// },// 禁掉全局的拖拽<a href="https://www.jb51.cc/tag/gongneng/" target="_blank" class="keywords">功能</a>。这样不会出现<a href="https://www.jb51.cc/tag/tupian/" target="_blank" class="keywords">图片</a>拖进<a href="https://www.jb51.cc/tag/yemian/" target="_blank" class="keywords">页面</a>的时候,把<a href="https://www.jb51.cc/tag/tupian/" target="_blank" class="keywords">图片</a>打开。
disableGlobalDnd: true,fileNumLimit: 300 //限制多<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a><a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a>的个数
//fileSizeLimit: 200 * 1024 * 1024,// 限制所有<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>的大小 200 M
//fileSingleSizeLimit: 50 * 1024 * 1024 // 限制单个<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>的大小 50 M
}); </pre>
后端
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.bear.upload.util.FileUtil;
import com.bear.upload.util.RETURN;
import com.bear.upload.vo.CheckMd5FileVO;
import com.bear.upload.vo.UploadVO;
@Service
public class ChunkUploadService {
private static Logger LOG = LoggerFactory.getLogger(ChunkUploadService.class);
@Value("${file.upload.path}")
private String UPLOAD_PATH;
private static final String Delimiter = "-";
/**
- 上传之前校验(整个文件、分片)
- @param md5FileVO
- @return
*/
public Object check(CheckMd5FileVO md5FileVO) {
Integer type = md5FileVO.getType();
Long chunk = md5FileVO.getChunk();
String fileName = md5FileVO.getFileName();
Long fileSize = md5FileVO.getFileSize();
if (type == 0) {// 未分片校验
String destfilePath = UPLOAD_PATH + File.separator + fileName;
File destFile = new File(destfilePath);
if (destFile.exists() && destFile.length() == fileSize) {
return RETURN.success("文件已存在,跳过",1);
} else {
return RETURN.success("文件不存在",0);
}
} else {// 分片校验
String fileMd5 = md5FileVO.getFileMd5();
String destFileDir = UPLOAD_PATH + File.separator + fileMd5;
String destFileName = chunk + Delimiter + fileName;
String destFilePath = destFileDir + File.separator + destFileName;
File destFile = new File(destFilePath);
if (destFile.exists() && destFile.length() == fileSize) {
return RETURN.success("分片已存在,跳过",1);
} else {
return RETURN.success("分片不存在",0);
}
}
}
/**
- 文件上传
- @param file
- @param uploadVO
- @param appVersion
- @return
*/
public Object upload(MultipartFile file,UploadVO uploadVO) {
Long chunk = uploadVO.getChunk();
if (chunk == null) {// 没有分片
return UnChunkUpload(file,uploadVO);
} else {// 分片
return ChunkUpload(file,uploadVO);
}
}
/**
- 分片上传
- @param file
- @param uploadVO
- @param appVersion
- @return
*/
public Object ChunkUpload(MultipartFile file,UploadVO uploadVO) {
String fileName = uploadVO.getName();
String fileMd5 = uploadVO.getFileMd5();
Long chunk = uploadVO.getChunk();// 当前片
Long chunks = uploadVO.getChunks();// 总共多少片
// 分片目录创建
String chunkDirPath = UPLOAD_PATH + File.separator + fileMd5;
File chunkDir = new File(chunkDirPath);
if (!chunkDir.exists()) {
chunkDir.mkdirs();
}
// 分片文件上传
String chunkFileName = chunk + Delimiter + fileName;
String chunkFilePath = chunkDir + File.separator + chunkFileName;
File chunkFile = new File(chunkFilePath);
try {
file.transferTo(chunkFile);
} catch (Exception e) {
LOG.error("分片上传出错",e);
return RETURN.fail("分片上传出错",1);
}
// 合并分片
Long chunkSize = uploadVO.getChunkSize();
long seek = chunkSize * chunk;
String destFilePath = UPLOAD_PATH + File.separator + fileName;
File destFile = new File(destFilePath);
if (chunkFile.length() > 0) {
try {
FileUtil.randomAccessFile(chunkFile,destFile,seek);
} catch (IOException e) {
LOG.error("分片{}合并失败:{}",chunkFile.getName(),e.getMessage());
return RETURN.fail("分片合并失败",1);
}
}
if (chunk == chunks - 1) {
// <a href="https://www.jb51.cc/tag/shanchu/" target="_blank" class="keywords">删除</a>分片<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>夹
FileUtil.deleteDirectory(chunkDirPath);
return RETURN.success("<a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a>成功",1);
} else {
return RETURN.fail("<a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a>中...",1);
}
}
/**
- 未分片上传
- @param file
- @param uploadVO
- @param appVersion
- @return
*/
public Object UnChunkUpload(MultipartFile file,UploadVO uploadVO) {
String fileName = uploadVO.getName();
// String fileMd5 = uploadVO.getFileMd5();
// 文件上传
File destFile = new File(UPLOAD_PATH + File.separator + fileName);
if (file != null && !file.isEmpty()) {
// 上传目录
File fileDir = new File(UPLOAD_PATH);
if (!fileDir.exists()) {
fileDir.mkdirs();
}
if (destFile.exists()) {
destFile.delete();
}
try {
file.transferTo(destFile);
return RETURN.success("上传成功",0);
} catch (Exception e) {
LOG.error("文件上传出错",e);
return RETURN.fail("文件上传出错",0);
}
}
return RETURN.fail("上传失败",0);
}
}