使用公共权限上传Amazon S3

31

我正在使用亚马逊的C# SDK并尝试上传文件,但默认情况下它具有受限权限。 我想让它公开可用,但似乎找不到如何在上传过程中执行此操作。

我的存储桶是公开的,但是当我使用下面的代码上传新文件时,我上传的文件不是公开的。

是否有人之前遇到过这种情况?

public class S3Uploader
{
    private string awsAccessKeyId;
    private string awsSecretAccessKey;
    private string bucketName;
    private Amazon.S3.Transfer.TransferUtility transferUtility;

    public S3Uploader(string bucketName)
    {
        this.bucketName = bucketName;
        this.transferUtility = new Amazon.S3.Transfer.TransferUtility("XXXXXXXXXXXXXXXXXX", "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");

    }

    public void UploadFile(string filePath, string toPath)
    {
        AsyncCallback callback = new AsyncCallback(uploadComplete);
        transferUtility.BeginUpload(filePath, bucketName, toPath, callback, null);
    }

    private void uploadComplete(IAsyncResult result)
    { 
        var x = result;
    }
}
5个回答

32

Tahbaza的解决方案是正确的,但它在AWS SDK的较新版本(2.1+)中不起作用...

考虑使用以下内容适用于SDK 2.1+版本:

private void UploadFileToS3(string filePath)
{
    var awsAccessKey = ConfigurationManager.AppSettings["AWSAccessKey"];
    var awsSecretKey = ConfigurationManager.AppSettings["AWSSecretKey"];
    var existingBucketName = ConfigurationManager.AppSettings["AWSBucketName"];
    var client = Amazon.AWSClientFactory.CreateAmazonS3Client(awsAccessKey, awsSecretKey,RegionEndpoint.USEast1);

    var uploadRequest = new TransferUtilityUploadRequest
    {
        FilePath = filePath,
        BucketName = existingBucketName,
        CannedACL = S3CannedACL.PublicRead
    };

var fileTransferUtility = new TransferUtility(client);
    fileTransferUtility.Upload(uploadRequest);
} 

也许对于OP来说有点晚了,但请注意SDK附带了一系列使用Task Parallel Library的异步上传和下载方法。用法是:await fileTransferUtility.UploadAsync(uploadRequest);这里是来自亚马逊的示例代码:http://blogs.aws.amazon.com/net/post/TxPJDGHVNCWHUJ/Amazon-S3-Transfer-Utility-for-Windows-Store-and-Windows-Phone - JJP
嗨,丹尼尔,如果我学习并使用上面的代码,上传的文件会是私有的吗?如果我粘贴对象URL,它会显示访问被拒绝吗? - Thomas Raj

18

找到了,需要使用TransferUtilityUploadRequest

public class S3Uploader
{
    private string awsAccessKeyId;
    private string awsSecretAccessKey;
    private string bucketName;
    private Amazon.S3.Transfer.TransferUtility transferUtility;

    public S3Uploader(string bucketName)
    {
        this.bucketName = bucketName;
        this.transferUtility = new Amazon.S3.Transfer.TransferUtility("XXXXXXXXXXXXXXXXXX", "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");

    }

    public void UploadFile(string filePath, string toPath)
    {
        AsyncCallback callback = new AsyncCallback(uploadComplete);
        var uploadRequest = new TransferUtilityUploadRequest();
        uploadRequest.FilePath = filePath;
        uploadRequest.BucketName = "my_s3_bucket";
        uploadRequest.Key = toPath;
        uploadRequest.AddHeader("x-amz-acl", "public-read");
        transferUtility.BeginUpload(uploadRequest, callback, null);
    }

    private void uploadComplete(IAsyncResult result)
    { 
        var x = result;
    }
}

1
只是提醒一下,您需要指定uploadRequest.BucketName才能使上传工作正常进行。 - John Dyer
2
在S3版本1之后,设置标头的方法已被弃用。TransferUtilityUploadRequest对象不再具有AddHeader方法。现在正确的答案是danielonthenet的。 - krillgar

5

我以前做过类似的事情,用的是C#,但没有使用过你们的库(所以我的帮助可能有限)。

这个想法是在文件中发送一个ACL头。

这是一种可以指导你方向的方法。

此外,这里有一些相关的AWS文档链接

    private const string AWS_ACL_HEADER = "x-amz-acl";

    private static string ToACLString(S3ACLType acl) {
        switch (acl) {
            case S3ACLType.AuthenticatedRead:
                return "authenticated-read";
            case S3ACLType.BucketOwnerFullControl:
                return "bucket-owner-full-control";
            case S3ACLType.BucketOwnerRead:
                return "bucket-owner-read";
            case S3ACLType.Private:
                return "private";
            case S3ACLType.PublicRead:
                return "public-read";
            case S3ACLType.PublicReadWrite:
                return "public-read-write";
            default: return "";
        }
    }

    public void Put(string bucketName, string id, byte[] bytes, string contentType, S3ACLType acl) {
        string uri = String.Format("https://{0}/{1}", BASE_SERVICE_URL, bucketName.ToLower());
        DreamMessage msg = DreamMessage.Ok(MimeType.BINARY, bytes);
        msg.Headers[DreamHeaders.CONTENT_TYPE] = contentType;
        msg.Headers[DreamHeaders.EXPECT] = "100-continue";
        msg.Headers[AWS_ACL_HEADER] = ToACLString(acl);
        Plug s3Client = Plug.New(uri).WithPreHandler(S3AuthenticationHeader);
        s3Client.At(id).Put(msg);
    }

谢谢帮忙处理报头。我发布了自己的答案,只是因为它使用标准的AWS库,利用S3多部分上传,允许您异步上传文件块,从而使上传速度更快。 - MattoTodd

2
您可以使用Amazon.S3.Model.PutObjectRequest的属性CannedACL来上传文件到S3,如下所示:
 var putObjectRequest = new Amazon.S3.Model.PutObjectRequest
                        {
                            BucketName = bucketName,
                            Key = key,
                            CannedACL = S3CannedACL.PublicReadWrite
                        }; 

2
考虑使用CannedACL方法,如下代码片段所示:
        string filePath = @"Path\Desert.jpg";
        Stream input = new FileStream(filePath, FileMode.Open);
        PutObjectRequest request2 = new PutObjectRequest();
        request2.WithMetaData("title", "the title")
            .WithBucketName(bucketName)
            .WithCannedACL(S3CannedACL.PublicRead)
            .WithKey(keyName)
            .WithInputStream(input);

1
AWS SDK 将此方法标记为已弃用,并将在 v2.0 中删除。 - winwaed

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接