本文处理的场景比较特殊,上传OSS文件由其他team掌控(无法操作),下载文件由本team所支持的服务器处理,然后需求方想要在下载OSS文件时,按照某种规则自定义下载文件的名称。这种多team合作的活,果然只能自己收敛。。。
方案探讨
与组内大神们探讨,目前找到三种解决方案:
- 修改oss文件元信息,变更Content-Disposition
- 文件下载到服务器,再进行包装
- 前端接入文件预览插件,弃用浏览器自带的文件预览功能
修改oss文件元信息
参考文档:阿里云对象存储OSS-管理文件元信息
下面贴出最主要的代码,主要是获取文件的ObjectMetadata,对其中的ContentDisposition更新配置:
- 预览模式:
meta.setContentDisposition("filename=" + newFileName)
- 附件模式:
meta.setContentDisposition("attachment;filename=" + newFileName)
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
try {
// 设置源文件与目标文件相同,调用ossClient.copyObject方法修改文件元信息。
CopyObjectRequest request = new CopyObjectRequest(sourceBucketName, sourceObjectName, destinationBucketName, destinationObjectName);
ObjectMetadata meta = new ObjectMetadata();
// 指定上传的内容类型。内容类型决定浏览器将以什么形式、什么编码读取文件。如果没有指定则根据文件的扩展名生成,如果没有扩展名则为默认值application/octet-stream。
meta.setContentType("text/plain");
// 设置内容被下载时的名称。
meta.setContentDisposition("Download File Name");
// 设置内容被下载时网页的缓存行为。
meta.setCacheControl("Download Action");
// 设置缓存过期时间,格式是格林威治时间(GMT)。
meta.setExpirationTime(DateUtil.parseIso8601Date("2022-10-12T00:00:00.000Z"));
// 设置内容被下载时的编码格式。
meta.setContentEncoding("utf-8");
// 设置header。
meta.setHeader("<yourHeader>", "<yourHeaderValue>");
// 设置自定义元信息property值为property-value。
meta.addUserMetadata("property", "property-value");
request.setNewObjectMetadata(meta);
// 修改元信息。
ossClient.copyObject(request);
} catch (OSSException oe) {
// do exception
} catch (ClientException ce) {
// do exception
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
下载到服务器并包装
未实现,主要说下思路:
- 将oss文件下载到服务器,对文件名重新命名
- 以文件流方式返回给前端
前端引入文件预览插件
引入vue-pdf插件,自行控制预览效果及下载~
其他实现方式参考文献:用VUE下载OSS文件的时候怎么改名字
跨域
终极思路:在文件服务器设置跨域规则
案例1: 访问阿里云/腾讯云服务对象存储OSS
- 解决方案:在oss控制平台,设置跨域规则
- 参考1:vuepdf 腾讯cos 跨域
案例2: 访问team服务器文件
- 服务器跨域配置:nginx/代码配置
方案对比
方案 | 优点 | 缺点 |
---|---|---|
修改oss文件元信息 | 实现简单,在原有读取oss文件流程中加修改元信息 | 会修改oss文件最后更新时间,若业务依赖此时间会有影响 |
下载到服务器并包装 | 对oss文件不做任何处理 | 服务器IO压力大;oss文件时效性没有作用了 |
前端引入文件预览插件 | 对oss文件不做任何处理 | 增加前端工作量,她们会打死后端的~ |