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

可信网站认证必须做吧广东网站优化公司

可信网站认证必须做吧,广东网站优化公司,外贸网站建设哪里做得好,宁波网站建设公司在哪里今天受到一个需求,需要查出文件,然后将文件打包后下载。看了下项目里默认代码有压缩功能,以此修改了下,项目使用了hutool。项目是若依项目 定义zip的数据传输对象,ossId可以是文件表的id Data public class SysOssZi…

今天受到一个需求,需要查出文件,然后将文件打包后下载。看了下项目里默认代码有压缩功能,以此修改了下,项目使用了hutool。项目是若依项目

定义zip的数据传输对象,ossId可以是文件表的id

@Data
public class SysOssZipDTO {/*** 关联OSS对象存储ID*/
})private String ossId;/*** 压缩包文件内文件夹路径,例子(main/java/com/haoyu/flowForm/domain/)*/private String zipItemFolderPath;}

sevice层

void downloadZip(List<SysOssZipDTO> zipDtoList, HttpServletResponse response, String taskId) throws IOException;

serviceImpl层

 @Overridepublic void downloadZip(List<SysOssZipDTO> zipDtoList, HttpServletResponse response, String taskId) throws IOException {if(zipDtoList == null || zipDtoList.isEmpty()){return;}ZipOutputStream zip = new ZipOutputStream(response.getOutputStream());final int bufferSize = 1024 * 1024 * 5;      // 5MBfinal byte[] buffer = new byte[bufferSize];long totalFileSize = 0;  // 文件总大小,估计值// 任务进度keyfinal String progressKey = OssConstant.SYS_OSS_PROGRESS+taskId;for (int i =0;i<zipDtoList.size();i++){// 设置进度(可选,用于压缩进度查询,就是将进度存入redis里,然后设计个接口供前端查询进度)/*SysOssProgressBO sysOssProgressBO = new SysOssProgressBO();sysOssProgressBO.setProgressNumber(Long.valueOf(i));sysOssProgressBO.setTotalProgress(Long.valueOf(zipDtoList.size()));RedisUtils.setCacheObject(progressKey,sysOssProgressBO, Duration.ofMinutes(10));*/SysOssZipDTO zipDTO = zipDtoList.get(i);if(StrUtil.isEmpty(zipDTO.getOssId())|| StrUtil.isEmpty(zipDTO.getZipItemFolderPath())){continue;}// 通过id查找文件信息SysOssVo sysOss = matchingUrl(SpringUtils.getAopProxy(this).getById(zipDTO.getOssId()));if (ObjectUtil.isNull(sysOss)) {continue;}// 通过文件信息获取文件流,本文用的Oss存储,如果用别的可以自己写,核心就是读取流OssClient storage = OssFactory.instance(sysOss.getService());try(InputStream inputStream = storage.getObjectContent(sysOss.getUrl());){// 这里使用文件名了,拼上前缀序号解决文件名重复问题zip.putNextEntry(new ZipEntry(zipDTO.getZipItemFolderPath() +"("+i+")"+sysOss.getOriginalName().replaceAll("/","_" )));int available = inputStream.available();totalFileSize += available;// 防Oom,可以用下面注释的也可以用hutool的/*int len = 0;while((len = inputStream.read(buffer)) != -1){zip.write(buffer, 0, len);}*/IoUtil.copy(inputStream, zip, bufferSize);zip.flush();zip.closeEntry();}catch (Exception e) {throw new ServiceException(e.getMessage());}}IoUtil.close(zip);// 生成zip文件// 由于前面已经开启了response的outputstream,所以这里不能调用reset()方法,否则会导致流异常关闭
//        response.reset();response.addHeader("Access-Control-Allow-Origin", "*");response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");response.addHeader("Content-Length", "" + totalFileSize);response.setContentType("application/octet-stream; charset=UTF-8");// 下载后的文件名可以由前端控制,此处由前端控制所以注释掉了/*if(StrUtil.isNotEmpty(zipName)){FileUtils.setAttachmentResponseHeader(response, zipName + ".zip");}*/}

其中的文件查询进度是可选的,可以让前端生成个任务id传到服务器
controller层

@GetMapping("/downloadZipByTrainId/{trainId}")public void downloadZipByTrainId(HttpServletResponse response, @PathVariable String trainId) throws IOException {// downloadZipByTrainId()方法里面调用downloadZip()this.iTrainMaterialsService.downloadZipByTrainId(trainId,response);}

前端代码,此处使用的是vue3

// 需要npm安装file-saver
import { saveAs } from 'file-saver'// 点击按钮触发事件
const clickDownLoadMaterials = async (row) =>{if(row.materialCount > 0 ){let res = await zip(`/train/trainMaterials/downloadZipByTrainId/${row.id}?projectName=${row.trainName}`,`${row.trainName}`)}else{ElMessage({message: '暂无材料可下载!',type: 'warning',})}
}const zip = (url, name) => {isShowLoadingDownLoadMaterial.value = trueurl = baseURL + urlaxios({method: 'get',url: url,responseType: 'blob',headers: {// 请求头token'Authorization': 'Bearer ' + getToken()}}).then(async (res) => {if(res.status == 200){isShowLoadingDownLoadMaterial.value = false}const isLogin = await blobValidate(res.data);if (isLogin) {const blob = new Blob([res.data], { type: 'application/zip' })saveAss(blob, name)} else {await this.printErrMsg(res.data);}})
}const saveAss = (text, name, opts) =>{saveAs(text, name, opts);
}// 验证是否为blob格式
export async function blobValidate(data) {try {const text = await data.text();JSON.parse(text);return false;} catch (error) {return true;}
}

杂谈
这次的需求整理到了不少东西,一开始担心oom的问题,于是调试时改变了缓冲区大小,发现java使用的内存也会对应的发生变化,这是为什么呢?实际上原因很简单,final byte[] buffer = new byte[bufferSize];这个变量就是占用这么多字节的内存呀!

当缓冲区设成0的时候,会发现读的特别特别慢,这是为什么呢?这是由于读的大小太小了,java调取磁盘io的频率变多,而调取磁盘io是一个特别消耗资源的行为也特别慢,因此就慢了。设置合适的缓冲区大小,可以一次性读取对应大小的内容从而减少磁盘io的交互从而提升效率,但也要避免缓冲区过大导致变量占用内存过大而oom。

同时,java流的操作不是一次性将整个文件都读入内存中的,而是仅仅获取文件的句柄,同时读偏移量,不停的读,移动偏移量,直至文件读写结束(大佬原话)。而且系统加载文件到内存也是按块加载的,并不会一次性全读到内存中(如一个几十g的游戏,打开并不会占用几十g内存,而是用到的时候在加载,不足的时候就会根据算法按页或者按块替换)

最后,开了流一定要关流!response.getOutputStream()自带的流可以不用手动关servlet在请求结束的时候会自己关掉

http://www.khdw.cn/news/68731.html

相关文章:

  • 医院网站建设模板下载深圳网站优化平台
  • wordpress easy smtp桂平seo快速优化软件
  • 品牌建设题目优化设计四年级上册数学答案
  • 广州白云做网站的公司考研培训班集训营
  • 自建网站餐饮服务提供者微信推广平台怎么做
  • 做销售在哪个网站找客户深圳关键词优化平台
  • 做电影网站模板教学设计广州品牌营销服务
  • 好学校平台网站模板下载免费论坛建站系统
  • 大湾区vi设计公司seo关键词是什么
  • 如何提升网站转化率凡科建站代理
  • 网站建设期末作业seo推广排名
  • 泰州网站建设电话百度注册公司地址
  • 广州制作网站报价火爆产品的推广文案
  • 网站标题优化工具同城发广告的平台有哪些
  • 做管道方面的网站app制作公司
  • php与dw怎么做校园网站浙江搜索引擎优化
  • 江苏网站建设价格网络营销前景和现状分析
  • 如何做企业网站的排名全国疫情又严重了
  • 专门做课件的网站成功的软文推广
  • 校园网站模板seo门户网站建设方案
  • 个人建筑资格证书查询优化大师使用方法
  • 网站开发项目需要什么人员今日最新重大新闻
  • 什么网站专门做批发互联网推广方案
  • 什么网站可以做调察问卷如何找到网络公关公司
  • 微信网站的结构优化大师班级
  • 企业网站后台管理系统视频网站推广
  • 保健品网站建设方案书模板南京企业网站排名优化
  • 网站建设赚钱网络推广都有什么方式
  • 阿里巴巴外贸网站首页做竞价推广大概多少钱
  • 好的h5网站百度基木鱼建站