Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么当我设置包含“0”的响应头覆盖时,我的S3预签名请求无效+&引用;?_C#_Amazon S3 - Fatal编程技术网

C# 为什么当我设置包含“0”的响应头覆盖时,我的S3预签名请求无效+&引用;?

C# 为什么当我设置包含“0”的响应头覆盖时,我的S3预签名请求无效+&引用;?,c#,amazon-s3,C#,Amazon S3,我正在使用Amazon.NET SDK生成一个预签名URL,如下所示: public System.Web.Mvc.ActionResult AsActionResult(string contentType, string contentDisposition) { ResponseHeaderOverrides headerOverrides = new ResponseHeaderOverrides(); headerOverrides.ContentType = cont

我正在使用Amazon.NET SDK生成一个预签名URL,如下所示:

public System.Web.Mvc.ActionResult AsActionResult(string contentType, string contentDisposition)
{
    ResponseHeaderOverrides headerOverrides = new ResponseHeaderOverrides();
    headerOverrides.ContentType = contentType;
    if (!string.IsNullOrWhiteSpace(contentDisposition))
    {
        headerOverrides.ContentDisposition = contentDisposition;
    }

    GetPreSignedUrlRequest request = new GetPreSignedUrlRequest()
               .WithBucketName(bucketName)
               .WithKey(objectKey)
               .WithProtocol(Protocol.HTTPS)
               .WithExpires(DateTime.Now.AddMinutes(6))
               .WithResponseHeaderOverrides(headerOverrides);

    string url = S3Client.GetPreSignedURL(request);

    return new RedirectResult(url, permanent: false);
}
GET 1234567890 /blah/blabh/blah.svg?response-content-disposition=filename="blah.svg"&response-content-type=image/svg xml
ResponseHeaderOverrides headerOverrides = new ResponseHeaderOverrides();
headerOverrides.ContentType = "image/svg+xml";
除非我的
contentType
中包含
+
,否则此操作非常有效。例如,当我尝试获取SVG文件时,就会发生这种情况,该文件的内容类型为
image/SVG+xml
。在这种情况下,S3抛出一个
SignatureDesNotMatch
错误

错误消息显示如下所示的
StringToSign

public System.Web.Mvc.ActionResult AsActionResult(string contentType, string contentDisposition)
{
    ResponseHeaderOverrides headerOverrides = new ResponseHeaderOverrides();
    headerOverrides.ContentType = contentType;
    if (!string.IsNullOrWhiteSpace(contentDisposition))
    {
        headerOverrides.ContentDisposition = contentDisposition;
    }

    GetPreSignedUrlRequest request = new GetPreSignedUrlRequest()
               .WithBucketName(bucketName)
               .WithKey(objectKey)
               .WithProtocol(Protocol.HTTPS)
               .WithExpires(DateTime.Now.AddMinutes(6))
               .WithResponseHeaderOverrides(headerOverrides);

    string url = S3Client.GetPreSignedURL(request);

    return new RedirectResult(url, permanent: false);
}
GET 1234567890 /blah/blabh/blah.svg?response-content-disposition=filename="blah.svg"&response-content-type=image/svg xml
ResponseHeaderOverrides headerOverrides = new ResponseHeaderOverrides();
headerOverrides.ContentType = "image/svg+xml";
请注意,响应内容类型中有一个空格,它现在表示
image/svgxml
,而不是
image/svg+xml
。在我看来,这似乎是造成问题的原因,但什么是解决问题的正确方法呢


我应该对我的内容类型进行编码吗?用引号或别的什么把它括起来?文档中没有提到这一点。

的确很奇怪-我可以通过以下观察到的行为很容易地重现这一点:

  • +
    中由
    GetPreSignedURL()
    生成的URL替换为其编码形式
    %2B
    将生成一个工作URL/签名
    • 无论是否将
      /
      替换为其编码形式
      %2F
      ,这都是正确的
  • 在调用
    GetPreSignedURL()
    之前预先编码contentType(例如通过),无论生成的URL有何变化,都会产生无效签名

给定这个函数的可用性有多长,这有点令人惊讶,但我仍然认为它是一个bug——因此,最好在.BR>中对此进行查询。 更新:我刚刚意识到你已经在那里问了同样的问题,错误确实得到了确认,因此可以通过监视;)来找出正确的答案
更新:此错误已被SDK删除。

更新 此错误已在SDK中删除


变通办法 这是一个已确认的问题,因此,在他们发布修复程序之前,我将使用此黑客程序使其正常工作:

准确地指定内容类型,使其在响应标头中看起来像什么。因此,如果希望S3返回
image/svg+xml
的内容类型,请将其设置为如下所示:

public System.Web.Mvc.ActionResult AsActionResult(string contentType, string contentDisposition)
{
    ResponseHeaderOverrides headerOverrides = new ResponseHeaderOverrides();
    headerOverrides.ContentType = contentType;
    if (!string.IsNullOrWhiteSpace(contentDisposition))
    {
        headerOverrides.ContentDisposition = contentDisposition;
    }

    GetPreSignedUrlRequest request = new GetPreSignedUrlRequest()
               .WithBucketName(bucketName)
               .WithKey(objectKey)
               .WithProtocol(Protocol.HTTPS)
               .WithExpires(DateTime.Now.AddMinutes(6))
               .WithResponseHeaderOverrides(headerOverrides);

    string url = S3Client.GetPreSignedURL(request);

    return new RedirectResult(url, permanent: false);
}
GET 1234567890 /blah/blabh/blah.svg?response-content-disposition=filename="blah.svg"&response-content-type=image/svg xml
ResponseHeaderOverrides headerOverrides = new ResponseHeaderOverrides();
headerOverrides.ContentType = "image/svg+xml";
现在,继续并像往常一样生成预签名请求:

GetPreSignedUrlRequest request = new GetPreSignedUrlRequest()
  .WithBucketName(bucketName)
  .WithKey(objectKey)
  .WithProtocol(Protocol.HTTPS)
  .WithExpires(DateTime.Now.AddMinutes(6))
  .WithResponseHeaderOverrides(headerOverrides);

string url = S3Client.GetPreSignedURL(request);
最后,使用内容类型的正确URL编码值“修复”生成的URL:

url = url.Replace(contentType, HttpUtility.UrlEncode(contentType));

是的,这是一个肮脏的解决办法,但是,嘿,它对我有效!:)

你完全正确。事实上,我尝试了你所做的一切,并在我发布问题后得出了相同的结论!:)虽然URL在编码时起作用,但我注意到响应中的实际内容类型标头有时会出错。