实战篇:断点续传?文件秒传,springcloud微服务架构面试

6、readFully(byte[] b):这个方法的作用就是将文本中的内容填满这个缓冲区b。如果缓冲b不能被填满,那么读取流的过程将被阻塞,如果发现是流的结尾,那么会抛出异常;

7、FileChannel getChannel():返回与此文件关联的唯一FileChannel对象;

8、int skipBytes(int n):试图跳过n个字节的输入,丢弃跳过的字节;

RandomAccessFile的绝大多数功能,已经被JDK1.4的NIO的**「内存映射」**文件取代了,即把文件映射到内存后再操作,省去了频繁磁盘io

主菜

总结经验,砥砺前行:之前的实战文章中过多的粘贴了源码,影响了各位小伙伴的阅读感受。经过大佬的点拨,以后将展示部分关键代码,供各位赏析,源码可在**「后台」**获取。

文件分块

文件分块需要在前端进行处理,可以利用强大的js库或者现成的组件进行分块处理。需要确定分块的大小和分块的数量,然后为每一个分块指定一个索引值。

为了防止上传文件的分块与其它文件混淆,采用文件的md5值来进行区分,该值也可以用来校验服务器上是否存在该文件以及文件的上传状态。

  • 如果文件存在,直接返回文件地址;

  • 如果文件不存在,但是有上传状态,即部分分块上传成功,则返回未上传的分块索引数组;

  • 如果文件不存在,且上传状态为空,则所有分块均需要上传。

fileRederInstance.readAsBinaryString(file);

fileRederInstance.addEventListener(“load”, (e) => {

let fileBolb = e.target.result;

fileMD5 = md5(fileBolb);

const formData = new FormData();

formData.append(“md5”, fileMD5);

axios

.post(http + “/fileUpload/checkFileMd5”, formData)

.then((res) => {

if (res.data.message == “文件已存在”) {

//文件已存在不走后面分片了,直接返回文件地址到前台页面

success && success(res);

} else {

//文件不存在存在两种情况,一种是返回data:null代表未上传过 一种是data:[xx,xx] 还有哪几片未上传

if (!res.data.data) {

//还有几片未上传情况,断点续传

chunkArr = res.data.data;

}

readChunkMD5();

}

})

.catch((e) => {});

});

在调用上传接口前,通过slice方法来取出索引在文件中对应位置的分块。

const getChunkInfo = (file, currentChunk, chunkSize) => {

//获取对应下标下的文件片段

let start = currentChunk * chunkSize;

let end = Math.min(file.size, start + chunkSize);

//对文件分块

let chunk = file.slice(start, end);

return { start, end, chunk };

};

之后调用上传接口完成上传。

断点续传、文件秒传

后端基于spring boot开发,使用redis来存储上传文件的状态和上传文件的地址。

如果文件完整上传,返回文件路径;部分上传则返回未上传的分块数组;如果未上传过返回提示信息。

在上传分块时会产生两个文件,一个是文件主体,一个是临时文件。临时文件可以看做是一个数组文件,为每一个分块分配一个值为127的字节。

校验MD5值时会用到两个值:

  • 文件上传状态:只要该文件上传过就不为空,如果完整上传则为true,部分上传返回false

  • 文件上传地址:如果文件完整上传,返回文件路径;部分上传返回临时文件路径。

/**

* 校验文件的MD5

**/

public Result checkFileMd5(String md5) throws IOException {

//文件是否上传状态:只要该文件上传过该值一定存在

Object processingObj = stringRedisTemplate.opsForHash().get(UploadConstants.FILE_UPLOAD_STATUS, md5);

if (processingObj == null) {

return Result.ok(“该文件没有上传过”);

}

boolean processing = Boolean.parseBoolean(processingObj.toString());

//完整文件上传完成时为文件的路径,如果未完成返回临时文件路径(临时文件相当于数组,为每个分块分配一个值为127的字节)

String value = stringRedisTemplate.opsForValue().get(UploadConstants.FILE_MD5_KEY + md5);

//完整文件上传完成是true,未完成返回false

if (processing) {

return Result.ok(value,“文件已存在”);

} else {

File confFile = new File(value);

byte[] completeList = FileUtils.readFileToByteArray(confFile);

List missChunkList = new LinkedList<>();

for (int i = 0; i < completeList.length; i++) {

if (completeList[i] != Byte.MAX_VALUE) {

//用空格补齐

missChunkList.add(i);

}

}

return Result.ok(missChunkList,“该文件上传了一部分”);

}

}

说到这,你肯定会问:当这个文件的所有分块上传完成之后,该怎么得到完整的文件呢?接下来我们就说一下分块合并的问题。

分块上传、文件合并

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
img

片转存中…(img-oTdSVdZW-1710926136246)]
[外链图片转存中…(img-OuCqw91C-1710926136246)]
[外链图片转存中…(img-MCnMQ4Fi-1710926136247)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
[外链图片转存中…(img-6QoniLEo-1710926136247)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值