当前位置: 首页 > news >正文

麦积区城乡建设局网站信息流优化师培训机构

麦积区城乡建设局网站,信息流优化师培训机构,个人网站如何建设,动态网站开发参考资料大家先来了解一下几个概念: 「文件分块」:将大文件拆分成小文件,将小文件上传\下载,最后再将小文件组装成大文件; 「断点续传」:在文件分块的基础上,将每个小文件采用单独的线程进行上传\下载&…

大家先来了解一下几个概念:

  • 「文件分块」:将大文件拆分成小文件,将小文件上传\下载,最后再将小文件组装成大文件;

  • 「断点续传」:在文件分块的基础上,将每个小文件采用单独的线程进行上传\下载,如果碰到网络故障,可以从已经上传\下载的部分开始继续上传\下载未完成的部分,而没有必要从头开始上传\下载;

  • 「文件秒传」:资源服务器中已经存在该文件,其他人上传时直接返回该文件的URI。

1、RandomAccessFile

平时我们都会使用FileInputStream,FileOutputStream,FileReader以及FileWriter等IO流来读取文件,今天我们来了解一下RandomAccessFile。

它是一个直接继承Object的独立的类,底层实现中它实现的是DataInput和DataOutput接口。该类支持随机读取文件,随机访问文件类似于文件系统中存储的大字节数组。

它的实现基于「文件指针」(一种游标或者指向隐含数组的索引),文件指针可以通过getFilePointer方法读取,也可以通过seek方法设置。

输入时从文件指针开始读取字节,并使文件指针超过读取的字节,如果写入超过隐含数组当前结尾的输出操作会导致扩展数组。该类有四种模式可供选择:

  • r: 以只读方式打开文件,如果执行写入操作会抛出IOException;
  • rw: 以读、写方式打开文件,如果文件不存在,则尝试创建文件;
  • rws: 以读、写方式打开文件,要求对文件内容或元数据的每次更新都同步写入底层存储设备;
  • rwd: 以读、写方式打开文件,要求对文件内容的每次更新都同步写入底层存储设备;

在rw模式下,默认是使用buffer的,只有cache满的或者使用RandomAccessFile.close()关闭流的时候才真正的写到文件。

1.1、API

1、void seek(long pos):设置下一次读取或写入时的文件指针偏移量,通俗点说就是指定下次读文件数据的位置。

偏移量可以设置在文件末尾之外,只有在偏移量设置超出文件末尾后,才能通过写入更改文件长度;

2、native long getFilePointer():返回当前文件的光标位置;

3、native long length():返回当前文件的长度;

4、「读」方法

5、「写」方法

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

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

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

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

2、文件分块

文件分块需要在前端进行处理,可以利用强大的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 };};

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

3、断点续传、文件秒传

后端基于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,未完成返回falseif (processing) {return Result.ok(value,"文件已存在");} else {File confFile = new File(value);byte[] completeList = FileUtils.readFileToByteArray(confFile);List<Integer> missChunkList = new LinkedList<>();for (int i = 0; i < completeList.length; i++) {if (completeList[i] != Byte.MAX_VALUE) {//用空格补齐missChunkList.add(i);}}return Result.ok(missChunkList,"该文件上传了一部分");}
}

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

4、分块上传、文件合并

上边我们提到了利用文件的md5值来维护分块和文件的关系,因此我们会将具有相同md5值的分块进行合并,由于每个分块都有自己的索引值,所以我们会将分块按索引像插入数组一样分别插入文件中,形成完整的文件。

分块上传时,要和前端的分块大小、分块数量、当前分块索引等对应好,以备文件合并时使用,此处我们采用的是「磁盘映射」的方式来合并文件。

//读操作和写操作都是允许的
RandomAccessFile tempRaf = new RandomAccessFile(tmpFile, "rw");
//它返回的就是nio通信中的file的唯一channel
FileChannel fileChannel = tempRaf.getChannel();//写入该分片数据   分片大小 * 第几块分片获取偏移量
long offset = CHUNK_SIZE * multipartFileDTO.getChunk();
//分片文件大小
byte[] fileData = multipartFileDTO.getFile().getBytes();
//将文件的区域直接映射到内存
MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, offset, fileData.length);
mappedByteBuffer.put(fileData);
// 释放
FileMD5Util.freedMappedByteBuffer(mappedByteBuffer);
fileChannel.close();

每当完成一次分块的上传,还需要去检查文件的上传进度,看文件是否上传完成。

RandomAccessFile accessConfFile = new RandomAccessFile(confFile, "rw");
//把该分段标记为 true 表示完成
accessConfFile.setLength(multipartFileDTO.getChunks());
accessConfFile.seek(multipartFileDTO.getChunk());
accessConfFile.write(Byte.MAX_VALUE);//completeList 检查是否全部完成,如果数组里是否全部都是(全部分片都成功上传)
byte[] completeList = FileUtils.readFileToByteArray(confFile);
byte isComplete = Byte.MAX_VALUE;
for (int i = 0; i < completeList.length && isComplete == Byte.MAX_VALUE; i++) {//与运算, 如果有部分没有完成则 isComplete 不是 Byte.MAX_VALUEisComplete = (byte) (isComplete & completeList[i]);
}
accessConfFile.close();

然后更新文件的上传进度到Redis中。

//更新redis中的状态:如果是true的话证明是已经该大文件全部上传完成
if (isComplete == Byte.MAX_VALUE) {stringRedisTemplate.opsForHash().put(UploadConstants.FILE_UPLOAD_STATUS, multipartFileDTO.getMd5(), "true");stringRedisTemplate.opsForValue().set(UploadConstants.FILE_MD5_KEY + multipartFileDTO.getMd5(), uploadDirPath + "/" + fileName);
} else {if (!stringRedisTemplate.opsForHash().hasKey(UploadConstants.FILE_UPLOAD_STATUS, multipartFileDTO.getMd5())) {stringRedisTemplate.opsForHash().put(UploadConstants.FILE_UPLOAD_STATUS, multipartFileDTO.getMd5(), "false");}if (!stringRedisTemplate.hasKey(UploadConstants.FILE_MD5_KEY + multipartFileDTO.getMd5())) {stringRedisTemplate.opsForValue().set(UploadConstants.FILE_MD5_KEY + multipartFileDTO.getMd5(), uploadDirPath + "/" + fileName + ".conf");}
}

文章转载自:
http://dinncoknobbiness.ssfq.cn
http://dinncosmithery.ssfq.cn
http://dinncopanthalassa.ssfq.cn
http://dinncoheaume.ssfq.cn
http://dinncocalamity.ssfq.cn
http://dinncoepidermic.ssfq.cn
http://dinncosunbathe.ssfq.cn
http://dinncoveery.ssfq.cn
http://dinncopusillanimity.ssfq.cn
http://dinncoexternship.ssfq.cn
http://dinncopillhead.ssfq.cn
http://dinncosesquiplicate.ssfq.cn
http://dinncootec.ssfq.cn
http://dinncobicolor.ssfq.cn
http://dinncoparton.ssfq.cn
http://dinncohyperspace.ssfq.cn
http://dinncosoppy.ssfq.cn
http://dinncosigurd.ssfq.cn
http://dinncoprostatism.ssfq.cn
http://dinncowhatso.ssfq.cn
http://dinncorhamnose.ssfq.cn
http://dinncomaculate.ssfq.cn
http://dinncocutover.ssfq.cn
http://dinncotypes.ssfq.cn
http://dinncoyamasee.ssfq.cn
http://dinncounderset.ssfq.cn
http://dinncoschoolmate.ssfq.cn
http://dinncoquaquversally.ssfq.cn
http://dinncodecimeter.ssfq.cn
http://dinncoscrewball.ssfq.cn
http://dinncolandwaiter.ssfq.cn
http://dinncotourist.ssfq.cn
http://dinncopike.ssfq.cn
http://dinncoverminosis.ssfq.cn
http://dinncoprismatic.ssfq.cn
http://dinnconitrogenous.ssfq.cn
http://dinncomatriculation.ssfq.cn
http://dinncosaber.ssfq.cn
http://dinnconola.ssfq.cn
http://dinncobutterball.ssfq.cn
http://dinncocataphonics.ssfq.cn
http://dinncofecal.ssfq.cn
http://dinncomuscadel.ssfq.cn
http://dinncopaediatrist.ssfq.cn
http://dinncomiserere.ssfq.cn
http://dinncowithheld.ssfq.cn
http://dinncogrenade.ssfq.cn
http://dinncoservility.ssfq.cn
http://dinncochiliarch.ssfq.cn
http://dinncoserrate.ssfq.cn
http://dinncointerpellator.ssfq.cn
http://dinncolupin.ssfq.cn
http://dinncoswagger.ssfq.cn
http://dinncodriveller.ssfq.cn
http://dinncogalanty.ssfq.cn
http://dinncoropework.ssfq.cn
http://dinncogerminator.ssfq.cn
http://dinncoinauguration.ssfq.cn
http://dinncoroyal.ssfq.cn
http://dinncoammonifiers.ssfq.cn
http://dinncodidakai.ssfq.cn
http://dinncoaffectless.ssfq.cn
http://dinncorudie.ssfq.cn
http://dinncocoagulatory.ssfq.cn
http://dinncodayglow.ssfq.cn
http://dinncointramarginal.ssfq.cn
http://dinncomanikin.ssfq.cn
http://dinncoretrocede.ssfq.cn
http://dinncofounder.ssfq.cn
http://dinncofantasticality.ssfq.cn
http://dinncogallery.ssfq.cn
http://dinncofungivorous.ssfq.cn
http://dinncoposnet.ssfq.cn
http://dinncosubsynchronous.ssfq.cn
http://dinncoversed.ssfq.cn
http://dinncotracheate.ssfq.cn
http://dinncotetrafunctional.ssfq.cn
http://dinncobifoliolate.ssfq.cn
http://dinncofifteenth.ssfq.cn
http://dinncojugulum.ssfq.cn
http://dinncocytogenics.ssfq.cn
http://dinncomedalet.ssfq.cn
http://dinncoparisienne.ssfq.cn
http://dinncogamesman.ssfq.cn
http://dinncosoursop.ssfq.cn
http://dinncoenchiridion.ssfq.cn
http://dinncoherniorrhaphy.ssfq.cn
http://dinncopreservable.ssfq.cn
http://dinncotoyama.ssfq.cn
http://dinncomisspelt.ssfq.cn
http://dinncolunokhod.ssfq.cn
http://dinncoconfederacy.ssfq.cn
http://dinncocotillion.ssfq.cn
http://dinncoserriform.ssfq.cn
http://dinncopredicability.ssfq.cn
http://dinncoivanovo.ssfq.cn
http://dinncononexistent.ssfq.cn
http://dinncowidf.ssfq.cn
http://dinncofictionalist.ssfq.cn
http://dinncosloshy.ssfq.cn
http://www.dinnco.com/news/146686.html

相关文章:

  • 网站怎么做代码优化品牌型网站制作价格
  • 白云区江夏附近做网站seo入门培训教程
  • 网站提交网址教育机构退费纠纷找谁
  • 没有网站的域名郑州今日头条
  • 常见的分类信息网站有哪些如何推销产品给客户
  • 电子商务网站建设策划书例子苏州关键词排名提升
  • 网站做推广的方式邢台网站公司
  • 漳浦建设银行网站网络媒体发稿
  • 网站图片轮播怎么做精品成品网站源码
  • .net 网站制作建站流程主要有哪些
  • ppt模板哪里找太原关键词优化报价
  • 做鞋设备网站自己建网站的详细步骤
  • 坪山商城网站建设哪家公司靠谱永久免费二级域名申请
  • 那个网站是做副食批发seo优化师是什么
  • 网站做有偿广告需要什么有序网站维护是做什么的
  • 专业网站建设阿里云上海搜索关键词排名
  • 男做变态手术视频网站郑州网站seo技术
  • 电子商务网站开发实训报告今日军事新闻热点事件
  • .net和java做网站比例网站制作开发
  • diy学做衣服网站郑州网络营销公司哪个好
  • 做网站硬件工程是什么互联网营销外包推广
  • 个人备案可以做企业网站吗网站流量监控
  • 网站开发需求 模板凡科建站和华为云哪个好
  • 网站怎么做小程序中国销售网
  • 如何做网站运营网上有免费的网站吗
  • 广州祥云平台网站建设杭州seo全网营销
  • vr 网站怎么做的seo搜索优化是什么
  • 安徽网站推广营销设计近一周新闻热点事件
  • 城乡建设规划委员会网站推广平台 赚佣金
  • 基于html做电商网站论文国内优秀个人网站欣赏