webuploader分片上传(前后端分离)

项目地址: https://download.csdn.net/download/zxcnlmx/10389632

功能描述

1、webuploader是百度研发的上传组件,文档不是特别规整,但是也够用了。

2、前端使用官网的上传图片demo,在此基础上代码略微调整做分片。既可以上传图片也可以上传文件。文件超过分片大小才启用分片。

3、分片上传已做md5校验,达到秒传的效果。分片以后需要合并,可以先分片后合并,也可以边分片边合并,本示例采用的是边分片边合并的方案。

4、后端用springboot做框架搭建。springMVC做rest服务,开启跨域访问。

5、容器用springboot内置的tomcat插件,运行Application的main方法即可启动服务;

显示效果

关键代码

前端

 

WebUploader.Uploader.register({
			'name': 'webUploaderHookCommand',
			'before-send-file': 'beforeSendFile',
			"before-send": "beforeSend"
		}, {
			beforeSendFile: function(file) {
				var task = new WebUploader.Deferred();
				fileName = file.name;
				fileSize = file.size;
				(new WebUploader.Uploader()).md5File(file, 0, 10 * 1024 * 1024).progress(function(percentage) {}).then(function(val) {
					fileMd5 = val;
					var url = checkUrl;
					var data = {
						type: 0,
						fileName: fileName,
						fileMd5: fileMd5,
						fileSize: fileSize
					};
					$.ajax({
						type: "POST",
						url: url,
						data: data,
						cache: false,
						async: false, // 同步
						timeout: 1000, // todo 超时的话,只能认为该分片未上传过
						dataType: "json",
						error: function(XMLHttpRequest, textStatus, errorThrown) {
							file.statusText = 'server_error';
							task.reject();
						}
					}).then(function(data, textStatus, jqXHR) {
						if(data.rtn == 0) {
							if(data.obj == 1) {
								file.statusText = 'file_existed';
								task.reject();
							} else {
								task.resolve();
							}
						} else {
							task.reject();
						}
					});
				});
				return task.promise();
			},
			beforeSend: function(block) {
				var task = new WebUploader.Deferred();
				var url = checkUrl;
				var data = {
					type: 1,
					fileName: fileName,
					fileMd5: fileMd5,
					chunk: block.chunk,
					fileSize: block.end - block.start
				};
				$.ajax({
					type: "POST",
					url: url,
					data: data,
					cache: false,
					async: false, // 同步
					timeout: 1000, // todo 超时的话,只能认为该分片未上传过
					dataType: "json"
				}).then(function(data, textStatus, jqXHR) {
					if(data.rtn == 0 && data.obj == 1) {
						task.reject(); // 分片存在,则跳过上传
					} else {
						task.resolve();
					}
				});
				this.owner.options.formData.fileMd5 = fileMd5;
				this.owner.options.formData.chunkSize = chunkSize;
				return task.promise();
			}
		});

		// 实例化
		uploader = WebUploader.create({
			pick: {
				id: '#filePicker',
				label: '点击选择文件'
			},
			formData: {
				uid: 123
			},
			dnd: '#dndArea', //指定文件拖拽的区域
			paste: '#uploader', //指定监听paste事件的容器,如果不指定,不启用此功能。此功能为通过粘贴来添加截屏的图片。建议设置为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/*'
			// },
			// 禁掉全局的拖拽功能。这样不会出现图片拖进页面的时候,把图片打开。
			disableGlobalDnd: true,
			fileNumLimit: 300 //限制多文件上传的个数
			//fileSizeLimit: 200 * 1024 * 1024, // 限制所有文件的大小 200 M
			//fileSingleSizeLimit: 50 * 1024 * 1024 // 限制单个文件的大小 50 M
		});

 

后端

 

import java.io.File;
import java.io.IOException;

import org.slf4j.Logger;
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) {
			// 删除分片文件夹
			FileUtil.deleteDirectory(chunkDirPath);

			return RETURN.success("上传成功", 1);
		} else {
			return RETURN.fail("上传中...", 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);
	}
}

Springboot之gif动态验证码

springboot2.1.7集成Mybatis插件—通用Mapper

Hbuild项目Android本地打包

 

 

 

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AM18

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值