我有锚标记显示文件名,点击时用于从S3网址下载文件。我的客户端现在要求我隐藏URL并在下载文件时不显示它,并在S3上使用唯一名称而不是可读文件名。下载时,需要将文件名更改为上载时指定的可读文件名。
有2个要求
努力1:使用锚标记
最简单的解决方案是创建临时锚标记并在该锚标记中使用download属性。
<a id="2135"></a>
<script>
function download(event) {
var fileData = getFileData(event);
var tempAnch = $('a').attr({href: fileData.url, download: fileData.name});
tempAnch.click();
tempAnch.remove();
};
</script>
这会下载文件但由于某些原因不会更改名称。经过多次改动后我无法解决。
努力2:使用Ajax方法
现在我尝试在JS端下载文件内容并将其保存到文件中。
$.ajax({
type: 'GET',
url: fileData.url,
dataType: 'text',
success: function(msg) {
var blob = new Blob([msg],
{type: fileData.mimeType});
saveAs(blob, fileData.name);
}
});
现在,此代码保存了具有所需名称的文件,并且文本文件的内容相同。但是对于Excel文件或xlsx文件,下载的文件已损坏。
是否有任何可能的解决方案可以下载xlsx,csv,txt或zip文件,而显示用户的网址,更改文件名下载?
答案 0 :(得分:0)
这不是那样的。您下载了一些东西,请求客户端知道它来自哪里。如果您想使链接只能使用一次或者对于特定的人,则需要通过应用程序服务器对其进行流式处理。
唯一的其他解决方案是在S3级别创建用户/权限,但即使这样,URL也会在某个时刻显示。
我不建议在每次下载时更改文件名。
也就是说,安装自己的网络服务器,创建下载密钥,然后让用户调用您的网址。根据要求,您可以传递文件并使密钥无效。
请注意,如果下载需要很长时间才能完成,通常会阻止您的网络服务器上的资源。示例1和1中的廉价PHP托管需要超过10个并发用户的工作(我试过: - ))
答案 1 :(得分:0)
尽管这个要求很荒谬,但是当你在本地保存文件时,这就是告诉浏览器如何调用它正在下载的文件:你需要S3来添加这个响应标题:
Content-Disposition: attachment; filename="the-desired-name.ext"
这可以通过两种方式完成:
选项1。
将文件上传到S3时,请发送该标头。每次下载时S3都会返回它,浏览器将使用该文件名。
选项2。
在您签名的网址中,告诉S3将此标头添加到响应中。这会将&response-content-disposition=attac...
添加到已签名的URL,S3将看到此内容并添加所需的响应标头。
如何执行此操作取决于您用于生成预签名URL的内容(即哪个SDK,或者如果您编写自己的SDK,就像我一样)。
此外,在生成预签名网址时,还有一个鲜为人知的功能,可让您在网址中找到您提供签名网址的对象。由于在不完全使URL无效的情况下无法更改或篡改已签名的URL,因此不鼓励用户“共享”他们可能发现的URL,因为URL会识别它们。 :)这是怎么做到的?您在签名前将x-amz-meta-{anything}={anything-else}
添加到网址。示例:...&x-amz-meta-downloaded-by=michael-sqlbot&...
。验证URL的S3部分将要求存在这些参数,以便URL与签名匹配,但实际返回正在下载的内容的S3部分将忽略它。
当然......如果您没有使用预先签名的网址,那么这就是您拥有的真正的问题......隐藏网址只是为了解决错误的问题。任何最低级别的用户都可以确定URL,并且我会声称通过尝试隐藏它无法实现真正的安全性好处。