大文件分片上传和断点续传
由于java天生缺陷 但是项目需要上传大文件,所以做了一个分片上传,话不多说.............................
UploadFileUtil.java 工具包 utils层
-
/**
-
* 分片上传与断点续传
-
*
-
* @param multipartFileParam 分片实体
-
* @param targetPath 目标路径
-
* @return 待定
-
*/
-
public ApiResult uploadAppendFile(MultipartFileParam multipartFileParam, String targetPath) {
-
String[] bin=multipartFileParam.getFileName ().split ("\\.");
-
Map<String, String> map = new HashMap<>();
-
if(!bin[1].equals ("bin")){
-
map.put("result", "文件格式错误");
-
log.error ("文件格式不对,请检查升级文件");
-
return ResultUtil.error (map);
-
}
-
-
-
-
long chunk = multipartFileParam.getChunkNumber();
-
long totalChunks = multipartFileParam.getTotalChunks();
-
long fileSize = multipartFileParam.getFileSize();
-
String taskId = multipartFileParam.getTaskId();
-
MultipartFile file = multipartFileParam.getFile();
-
String fileName = multipartFileParam.getFileName();
-
// String extName = FileUtil.extName(fileName);
-
// String separator = FileUtil.FILE_SEPARATOR;
-
String localPath = targetPath separator;
-
File tempFile = null;
-
RandomAccessFile raf = null;
-
InputStream is = null;
-
try {
-
if (chunk == 1) {
-
String tempFileName = taskId fileName.substring(fileName.lastIndexOf(".")) "_tmp";
-
File fileDir = new File(localPath);
-
if (!fileDir.exists()) {
-
fileDir.mkdirs();
-
}
-
tempFile = new File(localPath, tempFileName);
-
if (!tempFile.exists()) {
-
tempFile.createNewFile();
-
-
}
-
raf = new RandomAccessFile(tempFile, "rw");
-
is = file.getInputStream();
-
raf.seek(0);
-
int len = 0;
-
byte[] bytes = new byte[1024 * 10];
-
while ((len = is.read(bytes)) != -1) {
-
raf.write(bytes, 0, len);
-
}
-
raf.close();
-
is.close();
-
redisUtil.setObject(UpLoadConstant.chunkNum taskId, chunk, cacheTime);
-
redisUtil.setObject(UpLoadConstant.fastDfsPath taskId, tempFile.getPath(), cacheTime);
-
map.put("result", "上传成功");
-
} else {
-
String path = (String) redisUtil.getObject(UpLoadConstant.fastDfsPath taskId);
-
is = file.getInputStream();
-
raf = new RandomAccessFile(path, "rw");
-
raf.seek(fileSize);
-
int len = 0;
-
byte[] bytes = new byte[1024 * 10];
-
while ((len = is.read(bytes)) != -1) {
-
raf.write(bytes, 0, len);
-
}
-
redisUtil.setObject(UpLoadConstant.chunkNum taskId, chunk, cacheTime);
-
raf.close();
-
is.close();
-
}
-
String md5 = (String) redisUtil.getObject(UpLoadConstant.task taskId);
-
HashMap<String, String> redisMap = new HashMap<>();
-
redisMap.put("fileSize", fileSize "");
-
redisMap.put("taskId", taskId);
-
-
redisUtil.setHashAsMap(UpLoadConstant.fileMd5 md5, redisMap, cacheTime);
-
if (chunk == totalChunks) {
-
String path = (String) redisUtil.getObject(UpLoadConstant.fastDfsPath taskId);
-
// FileUtil.rename(new File(path), fileName, true);//改文件名称 原名
-
FileUtil.rename(new File(path), "upgrade.bin", true);//指定名称 upgrade.bin
-
map.put("result", "上传完毕");
-
redisUtil.del(UpLoadConstant.fileMd5 md5);
-
redisUtil.del(UpLoadConstant.task taskId);
-
redisUtil.del(UpLoadConstant.chunkNum taskId);
-
redisUtil.del(UpLoadConstant.fastDfsPath taskId);
-
}
-
} catch (IOException e) {
-
e.printStackTrace();
-
String md5 = (String) redisUtil.getObject(UpLoadConstant.task taskId);
-
redisUtil.del(UpLoadConstant.fileMd5 md5);
-
redisUtil.del(UpLoadConstant.task taskId);
-
redisUtil.del(UpLoadConstant.chunkNum taskId);
-
redisUtil.del(UpLoadConstant.fastDfsPath taskId);
-
map.put("result", "上传异常");
-
} finally {
-
try {
-
if (raf != null) {
-
raf.close();
-
}
-
} catch (IOException e) {
-
e.printStackTrace();
-
}
-
try {
-
if (is != null) {
-
is.close();
-
}
-
} catch (IOException e) {
-
e.printStackTrace();
-
}
-
}
-
return ResultUtil.success(map);
-
}
-
-
/**
-
* 校验md5值
-
*
-
* @param md5 md5
-
* @return map
-
*/
-
public Map<String, Object> checkMd5(String md5) {
-
Map<String, Object> map = new HashMap<>();
-
-
String fileSize = "";
-
String taskId = "";
-
md5 = SecureUtil.md5(md5);
-
Map redisMap = redisUtil.getMap(UpLoadConstant.fileMd5 md5);
-
if (MapUtil.isNotEmpty(redisMap)) {
-
fileSize = ( redisMap.get("fileSize").toString ());
-
taskId = ( redisMap.get("taskId").toString ());
-
}
-
if (StrUtil.isNotEmpty(fileSize)) {
-
map.put("fileSize", Long.parseLong(fileSize));
-
} else {
-
Map<String, Object> map1 = new HashMap<>();
-
taskId = IdUtil.simpleUUID();
-
map1.put("fileSize", 0);
-
map1.put("taskId", taskId);
-
redisUtil.setHashAsMap(UpLoadConstant.fileMd5 md5, map1, cacheTime);
-
redisUtil.setObject(UpLoadConstant.task taskId, md5, cacheTime);
-
map.put("fileSize", 0);
-
}
-
map.put("taskId", taskId);
-
return map;
-
}
RedisUtil.java 同为utils层
-
package vip.xiaonuo.sys.modular.upgrade.utils;
-
-
import org.springframework.data.redis.core.RedisTemplate;
-
import org.springframework.stereotype.Component;
-
import org.springframework.util.CollectionUtils;
-
-
import javax.annotation.Resource;
-
import java.util.List;
-
import java.util.Map;
-
import java.util.concurrent.TimeUnit;
-
-
/**
-
* @Author: geng
-
* @Date: 2022/9/23 21:49
-
* @Description:
-
*/
-
-
public class RedisUtil {
-
-
-
private RedisTemplate<String, Object> redisTemplate;
-
-
//写入对象
-
public boolean setObject(final String key, Object value, Integer expireTime) {
-
try {
-
-
redisTemplate.opsForValue().set(key, value);
-
redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
-
return true;
-
} catch (Exception e) {
-
e.printStackTrace();
-
return false;
-
}
-
}
-
-
//获取对象
-
public Object getObject(final String key) {
-
return key == null ? null : redisTemplate.opsForValue().get(key);
-
}
-
-
-
//写入集合
-
public boolean setList(final String key, Object value, Integer expireTime) {
-
try {
-
redisTemplate.opsForList().rightPush(key, value);
-
redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
-
return true;
-
} catch (Exception e) {
-
e.printStackTrace();
-
return false;
-
}
-
}
-
-
//获取集合
-
public List<Object> getList(final String key) {
-
try {
-
return redisTemplate.opsForList().range(key, 0, -1);
-
} catch (Exception e) {
-
e.printStackTrace();
-
return null;
-
}
-
}
-
-
public boolean setHashAsKV(String key, Object hk, Object hv, Integer expireTime) {
-
try {
-
redisTemplate.opsForHash().put(key, hk, hv);
-
redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
-
return true;
-
} catch (Exception e) {
-
e.printStackTrace();
-
}
-
return false;
-
}
-
-
public boolean setHashAsMap(String key, Map map, Integer expireTime) {
-
try {
-
redisTemplate.opsForHash().putAll(key, map);
-
redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
-
return true;
-
} catch (Exception e) {
-
e.printStackTrace();
-
}
-
return false;
-
}
-
-
public Map getMap(String key) {
-
Map<Object, Object> map = redisTemplate.opsForHash().entries(key);
-
if (CollectionUtils.isEmpty(map)) {
-
return null;
-
}
-
return map;
-
}
-
-
public Object getHashObject(String k1, String k2) {
-
return redisTemplate.opsForHash().get(k1, k2);
-
}
-
-
/**
-
* 判断是否存在key
-
*
-
* @param key key
-
* @return
-
*/
-
public boolean hasKey(final String key) {
-
try {
-
return redisTemplate.hasKey(key);
-
} catch (Exception e) {
-
e.printStackTrace();
-
}
-
return false;
-
}
-
-
/**
-
* 删除key
-
*
-
* @param key key
-
* @return
-
*/
-
public void del(final String key) {
-
if (hasKey(key)) {
-
redisTemplate.delete(key);
-
}
-
}
-
-
/**
-
* 批量删除key
-
*
-
* @param keys keys
-
* @return
-
*/
-
public boolean delKeys(String... keys) {
-
for (String key : keys) {
-
if (hasKey(key)) {
-
Boolean flag = redisTemplate.delete(key);
-
if (flag == null) {
-
continue;
-
}
-
if (!flag) {
-
return false;
-
}
-
}
-
}
-
return true;
-
}
-
}
entity层
-
package vip.xiaonuo.sys.modular.upgrade.entity;
-
-
import lombok.Data;
-
import org.springframework.web.multipart.MultipartFile;
-
-
import java.io.Serializable;
-
-
-
public class MultipartFileParam implements Serializable {
-
private static final long serialVersionUID = 3238600879053243080L;
-
private String taskId;//文件传输任务ID
-
private long chunkNumber;//当前为第几分片
-
private long chunkSize;//每个分块的大小
-
private long totalChunks;//分片总数
-
private long fileSize;
-
private String fileName;
-
private String identifier;//文件唯一标识
-
private MultipartFile file;//分块文件传输对象
-
-
}
UpLoadConstant.java constant层
-
package vip.xiaonuo.sys.modular.upgrade.constant;
-
-
/**
-
* @Author: geng
-
* @Date: 2022/9/23 22:00
-
* @Description:
-
*/
-
public class UpLoadConstant {
-
private final static String uploading = "Uploading:";
-
private final static String file = uploading "file:";
-
//当前文件传输到第几块
-
public final static String chunkNum = file "chunkNum:";
-
//当前文件上传到fastdfs路径
-
public final static String fastDfsPath = file "fastDfsPath:";
-
public final static String task = uploading "task:";
-
public final static String fileMd5 = file "md5:";
-
-
}
param层
-
package vip.xiaonuo.sys.modular.upgrade.param;
-
-
/**
-
* @Author: geng
-
* @Date: 2022/9/23 22:27
-
* @Description:
-
*/
-
public class ApiResult {
-
/**
-
* 错误码.
-
*/
-
private Integer code;
-
-
/**
-
* 提示信息.
-
*/
-
private String msg;
-
-
/**
-
* 具体的内容.
-
*/
-
private Object data;
-
-
public Integer getCode() {
-
return code;
-
}
-
-
public void setCode(Integer code) {
-
this.code = code;
-
}
-
-
public String getMsg() {
-
return msg;
-
}
-
-
public void setMsg(String msg) {
-
this.msg = msg;
-
}
-
-
public Object getData() {
-
return data;
-
}
-
-
public void setData(Object data) {
-
this.data = data;
-
}
-
}
-
package vip.xiaonuo.sys.modular.upgrade.param;
-
-
public enum CustomResponse {
-
SUCCESS(10000, "响应成功"),
-
FAILURE(10001, "响应失败");
-
private Integer code;
-
private String msg;
-
-
CustomResponse(Integer code, String msg) {
-
this.code = code;
-
this.msg = msg;
-
}
-
-
public Integer getCode() {
-
return code;
-
}
-
-
public String getMsg() {
-
return msg;
-
}
-
}
-
package vip.xiaonuo.sys.modular.upgrade.param;
-
-
/**
-
* @Author: geng
-
* @Date: 2022/9/23 22:28
-
* @Description:
-
*/
-
public class ResultUtil {
-
public static ApiResult success(Object object) {
-
ApiResult apiResult = new ApiResult();
-
apiResult.setCode(CustomResponse.SUCCESS.getCode());
-
apiResult.setMsg(CustomResponse.SUCCESS.getMsg());
-
apiResult.setData(object);
-
return apiResult;
-
}
-
-
public static ApiResult success() {
-
ApiResult apiResult = new ApiResult();
-
apiResult.setCode(CustomResponse.SUCCESS.getCode());
-
apiResult.setMsg(CustomResponse.SUCCESS.getMsg());
-
return apiResult;
-
}
-
-
public static ApiResult success(Integer code, String msg, Object obj) {
-
ApiResult apiResult = new ApiResult();
-
apiResult.setCode(code);
-
apiResult.setMsg(msg);
-
apiResult.setData(obj);
-
return apiResult;
-
}
-
-
public static ApiResult error(Object object) {
-
ApiResult apiResult = new ApiResult();
-
apiResult.setCode(CustomResponse.FAILURE.getCode());
-
apiResult.setMsg(CustomResponse.FAILURE.getMsg());
-
apiResult.setData(object);
-
return apiResult;
-
}
-
-
public static ApiResult errMsg(String msg) {
-
ApiResult apiResult = new ApiResult();
-
apiResult.setCode(CustomResponse.FAILURE.getCode());
-
apiResult.setMsg(msg);
-
return apiResult;
-
}
-
-
public static ApiResult error() {
-
ApiResult apiResult = new ApiResult();
-
apiResult.setCode(CustomResponse.FAILURE.getCode());
-
apiResult.setMsg(CustomResponse.FAILURE.getMsg());
-
return apiResult;
-
}
-
-
public static ApiResult error(Integer code, String msg, Object obj) {
-
ApiResult apiResult = new ApiResult();
-
apiResult.setCode(code);
-
apiResult.setMsg(msg);
-
apiResult.setData(obj);
-
return apiResult;
-
}
-
}
controller层
-
-
public ApiResult checkMd5("md5") String md5) { (
-
Map<String, Object> map = uploadFileUtil.checkMd5(md5);
-
return ResultUtil.success(map);
-
}
-
-
-
public ApiResult chunkUpload(MultipartFileParam multipartFileParam) {
-
return uploadFileUtil.uploadAppendFile(multipartFileParam, "D:\\klp");
-
}
前端代码
-
chunkUpload() {
-
-
const file = this.fileList[0]
-
const md5 = file.name file.size file.lastModified
-
-
chunkUploaMess(md5).then((res)=>{
-
if (res) {
-
console.log(res)
-
const start = Number(res.data.fileSize)
-
const taskId = res.data.taskId
-
if (res.data) {
-
-
this.upload(start, taskId, file)
-
} else {
-
this.upload(0, taskId, file)
-
}
-
-
})
-
-
}
-
upload(start, taskId, file) {
-
// 分片大小 5M
-
const bytePercent = 1024 * 1024 * 5
-
// 通过文件大小除以分片大小得出总片数
-
const totalChunks = Math.ceil(file.size / bytePercent)
-
// 起始位置 分片数 如果大于文件大小,那么终点位置就是文件大小,反之就是前者
-
const end = (start bytePercent) > file.size ? file.size : (start bytePercent)
-
const fileName = file.name
-
// 分片文件
-
const chunkFile = file.slice(start, end)
-
// 当前分片数
-
const currChunkNum =parseInt (start / bytePercent) 1
-
const formData = new FormData()
-
formData.append('file', chunkFile)
-
formData.append('fileName', fileName)
-
formData.append('fileSize', start)
-
formData.append('taskId', taskId)
-
formData.append('chunkNumber', currChunkNum)
-
formData.append('chunkSize', bytePercent)
-
formData.append('totalChunks', totalChunks)
-
-
uploadsMess(formData).then((res)=>{
-
if (res.data.result === '上传完毕') {
-
alert('成功')
-
} else {
-
-
this.upload(end, taskId, file)
-
}
-
})
-
-
-
},
api
-
/**
-
* 分片
-
* @returns {AxiosPromise}
-
* @param md5
-
*/
-
export function chunkUpload(md5) {
-
return axios({
-
url: '/main/checkMd5',
-
method: 'get',
-
data: md5,
-
})
-
}
-
/**
-
* 分片
-
* @returns {AxiosPromise}
-
* @param formData
-
*/
-
export function uploads(formData) {
-
return axios({
-
url: '/main/chunkUpload',
-
method: 'POST',
-
data: formData,
-
contentType: false,//很重要,指定为false才能形成正确的Content-Type
-
processData: false, //加入这属性 processData默认为true,为true时,提交不会序列化data。
-
})
-
}
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgbhhbf
系列文章
更多
同类精品
更多
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01