【问题标题】:Generating pre-signed S3 URL for file with spaces为带空格的文件生成预签名的 S3 URL
【发布时间】:2025-12-23 12:55:11
【问题描述】:

我试图生成一个预签名的 URL 链接以传递给客户端。只要文件不包含空格,我的逻辑就可以很好地工作。但是,如果确实如此,我会得到“指定的密钥不存在”。错误。

为了清楚起见,我正在获取 URL 本身并对其进行解析。所以,当我拿到钥匙时,它看起来像这样:

mybucket/my+file+with+spaces.pdf

因此,S3 SDK 似乎采用了加号并将其 URL 编码为 %2b,因此当单击链接时它无法识别路径。如果我重新编写将“+”放回去的链接,我会收到以下错误:

我们计算的请求签名与您提供的签名不匹配。检查您的密钥和签名方法。

【问题讨论】:

    标签: java amazon-web-services amazon-s3


    【解决方案1】:

    好吧,我找到了自己问题的答案。如果你只是将 + 替换为 " " 你会得到正确的结果。

    objectKey = file.replace("+", " ");
    

    【讨论】:

    • S3 做了一些奇怪的 URL 编码,可能无法修复,因为它已经这样 10 年了。您从哪里获得带有 + 符号的原始 URL?我问,因为您的解决方案可能有效但不完整。
    • @Michael-sqlbot 感谢您的评论!我从另一个应用程序的事件中获取 url。该应用程序将文档上传到 kms 加密位置并将事件传递给我。我提取文档链接并生成过期链接。你觉得这有什么问题吗?
    • 您可能应该使用一个库来解码 url-escaping 并传递您通过那里获得的值。如果文件名实际上包含文字 +,则其他应用程序应该向您发送 %2B,如果您将其传递给 SDK,它将以 %252B 的形式发送到 S3(将 % 转义为 %25)这也被破坏了,接收到的任何其他百分比编码文字也是如此。对您收到的值使用 url-decoding 应该将它们转换回正常值,以便 SDK 具有可使用的标准化值。这就是为什么我怀疑您的修复只能解决您目前看到的一个问题。
    • 这是很好的建议@Michael-sqlbot!谢谢!应该给更多的时间让你回答!
    • @Michael-sqlbot 看起来我总是得到文件名中带有“+”的链接,所以用空格替换它们似乎是合理的。但是,如果这种情况发生变化,它可能会很微妙。正在寻找解决方案...
    【解决方案2】:

    您是否从另一个事件(例如 SQS、SNS)中获取您的 S3 对象密钥?因此,您的密钥可能已经经过 URL 编码。在将对象密钥提供给预签名 URL 生成器之前进行 URL 解码。

    当您请求签名 URL 时,对象键不应进行 URL 编码。

    (我只是在这里写下我的经验,以便其他遇到同样问题的人会有所帮助。)

    【讨论】: