4

我正在尝试使用适用于 .NET 的 AWS 开发工具包从 Amazon s3 检索一些 HTML 文件。我能够获取 HTML 文件,但链接到网页的图像没有显示,也没有应用相关的样式表。现在,我明白为什么会这样了。因为每个图像和样式表在 Amazon s3 中都是一个单独的对象,而我的代码只是为 HTML 文件创建预签名 URL:

 private void GetWebUrl()
{
        var request =
                new GetPreSignedUrlRequest().WithBucketName(bucketName)
                  .WithKey("test/content.htm");
            request.WithExpires(DateTime.Now.Add(new TimeSpan(0, 0, 0, 50)));
            var url = S3.GetPreSignedURL(request);
            Iframe2.Attributes.Add("src", url);
}

访问与此 HTML 文件相关的图像和样式表的最佳方式是什么?我可以查找所有图像,然后使用上述方法生成预签名的 URL 请求,但这不是一种有效的方法,我无法将图像和样式表公开。有没有其他人遇到过类似的问题?此外,如果我使用 Rest API 对用户进行身份验证(使用身份验证标头)会更好,这样浏览器将在标头中包含身份验证信息,而我不必为每个对象创建预签名的 URL。一小段 REST API 代码会很有帮助。

4

1 回答 1

1

实现此目的的最佳方法是使用通用处理程序 (.ASHX)。诀窍是将网页和相关对象的来源更改为您的处理程序:

src:"StreamFile.ashx?file="ObjKey"

现在,要更改源,您可以更新旧的 HTML 文件并使用指向 (StreamFile.ashx)Generic Handler 的源创建新文件,或者使用 URL 重写将旧 URL 写入新 URL。这可以在 IIS 或 web.config 中完成。如果您在 IIS 中执行此操作,它将自动在您的 web.config 中添加代码。

<system.webServer>
    <rewrite>
      <rules>
        <rule name="Content">
          <match url="DevelopmentContent/Course/([a-zA-Z0-9]+)" />
          <action type="Rewrite" url="StreamFile.ashx/?file=course{R:1}" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>

上面的代码将在 Src 字符串中查找“DevelopmentContent/Course/”,如果找到,会将 URL 重写为 StreamFile.ashx/?file=course{R:1}。R:1 将其余的 URL 粗体部分(DevelopmentContent/Course/ xyz/xsd/x/sd/ds.htm)映射到您在亚马逊 S3 中的对象键。现在 StreamHandler.ashx 将接收来自的请求具有指定 URL 的服务器。然后,您可以从查询字符串(context.Request.QueryString["file"]) 中获取对象键,然后创建一个函数来获取所需的对象。

public void ProcessRequest(HttpContext context)
        {           
            var response = Gets3Response(context.Request.QueryString["file"]);
            if (response != null)
            {
                using (response)
                {
                    var mimEtype = response.ContentType;
                    context.Response.ContentType = mimEtype;
                    using (var responseStream = response.ResponseStream)
                    {
                        var buffer = new byte[8000];
                        var bytesRead = -1;
                        while ((bytesRead = responseStream.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            context.Response.OutputStream.Write(buffer, 0, bytesRead);
                        }
                    }
                    context.Response.Flush();
                    context.Response.End();
                }
            }
            else
            {

                context.Response.Write("Unable to retrieve content!");

            }
        }




        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
    private static GetObjectResponse Gets3Response(string fileName)
        {
            GetObjectResponse response;
            if (fileName.Trim().Length == 0)
            {
                return null;
            }
            try
            {
                var request = new GetObjectRequest();
                request.WithBucketName(BucketName).WithKey(fileName);
                response = AmazonS3ClientProvider.CreateS3Client().GetObject(request);
            }
            catch (AmazonS3Exception amazonS3Exception)
            {
                if (amazonS3Exception.ErrorCode != null &&      (amazonS3Exception.ErrorCode.Equals("InvalidAccessKeyId") || amazonS3Exception.ErrorCode.Equals("InvalidSecurity")))
                {
                }
                return null;
            }
            catch (Exception ex)
            {
                return null;
            }

            return response;
        }

所以现在所有的 HTTP 请求都将使用您的服务器作为代理进行。

于 2012-05-29T06:09:56.710 回答