前提:
本文建立在文件的权限是Private的情况下,且使用PHP SDK示范。Public权限与其它语言请自行根据原理进行尝试
需求:
生成object的强制下载链接,要求不论任何格式打开链接后都是直接下载,而不是可能被浏览器渲染
过程(瞎叨叨几句,大可跳过~):
首先自然是去文档找答案,但是看来看去,生成访问链接只有单纯的生成一个能访问的链接。通过浏览器打开,支持的格式会被直接渲染。。尴尬。。
然后就是搜索,想要借用别人的前车之鉴,结果发现特么根本搜不到有用的信息...难不成就没有人有过这种需求??
好吧,再接下来只能申请官方帮助了,提交了一个工单。结果,,好嘛,,他告诉我直接修改文件的元信息。。下载是能下载了,可是特么的我要预览的链接怎么办?关闭工单,放弃官方。。
最终,仔细梳理整个链接的生成过程,并且发现sub-resource的存在,几经尝试,大功告成。。真特么不容易啊。。
解决方案原理:
一个正常的资源链接,如果想要其强制下载,那么解决方案就是设置response的header头:Content-Disposition: attachment;filename="filename",其中 "filename" 代表默认下载的文件名。当浏览器解析到此header头时,便会不执行渲染而直接下载
到了oss这里亦然。但是因为response是由阿里云配置,所以我们需要能够设置其header头,把disposition放进去,从而强制下载。那么,如何才能设置??
最终翻来覆去文档,且结合自己猜想,发现在签名URL(访问链接)后面可以加所谓的sub-resource。而这里面有个参数叫response-content-disposition,当指定其后,阿里云便会将其内容加到response的Content-Disposition中,实现强制下载。而与此同时,因为签名的生成规则,它需要object+sub-resource作为object整体来生成签名URL。所以,我们需要做的就是使用object+sub-resource生成签名,然后再在访问链接上加上sub-resource,即可实现强制下载的需求。 以下为示例代码
说明一下:
1、app('aliyun_oss')获取到的是OSSClient,我在项目中进行的封装(laravel),各位请根据实际情况灵活获取实例
2、最后两行代码:生成签名url后,返回的链接并不能正常使用,因为它把object+sub-resource当做object并且进行了urlencode,导致其在url是一个路径,代表的是object的key,访问其便会提示object不存在的报错(至少在PHP SDK中是这样)。而我们需要的是sub-resource当做url的其中一个参数,所以需要处理一下。看不懂php的没关系,举个转换前后的例子,自行处理便可:
http://my-oss.oss-cn-beijing.aliyuncs.com/test.png%3Fresponse-content-disposition%3Dattachment%3Bfilename%3D%E6%96%B0%E7%AA%81%E7%A0%B4.png?OSSAccessKeyId=YOURKEY&Expires=1552621068&Signature=YOURSIGNATURE
http://my-oss.oss-cn-beijing.aliyuncs.com/test.png?response-content-disposition=attachment;filename=%E6%96%B0%E7%AA%81%E7%A0%B4.png&OSSAccessKeyId=YOURKEY&Expires=1552621036&Signature=YOURSIGNATURE
3、downName的rawurlencode,为了浏览器兼容