I\'m using the Amazon C# SDK and trying to upload a file, but by default it has restricted permissions. I would like to make it publicly available, but I can\'t seem to find ou
The solution by Tahbaza is correct, but it doesn't work in the later versions of AWS SDK (2.1+)...
Consider using the following for 2.1+ versions of SDK:
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);
}
You can use the property CannedACL of Amazon.S3.Model.PutObjectRequest to upload files to S3 as shown below,
var putObjectRequest = new Amazon.S3.Model.PutObjectRequest
{
BucketName = bucketName,
Key = key,
CannedACL = S3CannedACL.PublicReadWrite
};
Found it, need to use a 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;
}
}
I have done this before, and in C#, but not with your library (so this may be of limited help).
The idea is to send an ACL header along with the file.
This is one way to do it that should point you in the right direction.
Here's also a link to some relevant AWS docs.
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);
}
Consider CannedACL approach, shown in the follwing snippet:
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);