从Amazon S3账户转移文件到另一个账户

4

我正在编写一个应用程序,需要在不同的s3账户之间传输文件,我们不想在上传到目标s3账户之前将文件保存在本地。
因此,我们使用以下代码获取源文件流:

public Stream GetFileStream(string path)
{
    var pathPieces = path.Split('/');
    string bucket = pathPieces[0];
    string fileName = pathPieces[pathPieces.Length - 1];

    GetObjectRequest request = new GetObjectRequest();
    request.BucketName = bucket;
    request.Key = fileName;

    GetObjectResponse response = Client.GetObject(request);

    return response.ResponseStream;
}

之后我们使用这个流来上传到目的地:

    TransferUtility transferUtility = new TransferUtility(Client);
    transferUtility.S3Client.PutBucket(new PutBucketRequest() { UseClientRegion = true }.WithBucketName(bucket));
    TransferUtilityUploadRequest request = new TransferUtilityUploadRequest()
    .WithBucketName(bucket)
    .WithKey(key)
    .WithPartSize(1024)
    .WithTimeout(100 * 60 * 60 * 1000)
    .WithAutoCloseStream(true)
    .WithCannedACL(S3CannedACL.PublicReadWrite)
    .WithInputStream(fileStream) as TransferUtilityUploadRequest;

    transferUtility.Upload(request);

但是在最后一行“上传”功能调用时,我总是会遇到这个错误:该流不支持寻址操作。

是否有其他方法可以实现我想要做的事情?因为它似乎不是正确的方法。


在某种程度上,当进行流媒体时,您无论如何都会下载整个文件并将其上传回相同的文件,这里不会节省任何带宽,相反,让它保存为本地文件,然后再上传。不必要地阻塞内存缓冲区或阻塞网络操作,这不是一个好的做法。 - Akash Kava
我的想法是获取一些字节[缓冲区大小]并传输它们,然后获取其他字节并传输它们,如果同时传输100 GB的文件,我的硬盘不会变满。如果我有错误,请纠正我。 - Amr Elgarhy
1
对于如此巨大的文件,无论如何都会失败,对于100GB的文件传输,会有许多网络故障,而对于上传,S3需要首先知道文件长度,以便将文件分成多个部分并同时上传。因此,在不先下载整个文件的情况下,传输工具将无法正常工作。 - Akash Kava
3个回答

2
我遇到了这个问题,并发布了我用来解决它的方法。借鉴了Jon Skeet的一些代码。对我有用,但我知道它有点笨拙,可能可以改进。
string filename = "nameoffiletocopy"

using (Stream stream = GetS3Stream(filename))
{
    AmazonS3Config config = new AmazonS3Config 
        {CommunicationProtocol = Protocol.HTTP};
    AmazonS3 client = 
        AWSClientFactory.CreateAmazonS3Client(
            "destinationaccesskey",
            "destinationsecretacceskey", 
            config);
    string destinationBucketName = "destinationbucketname";

    PutObjectRequest request = new PutObjectRequest
    {
        BucketName = destinationBucketName,
        InputStream = stream,
        Key = filename,
        CannedACL = S3CannedACL.PublicRead
    };

    PutObjectResponse response = client.PutObject(request);     
}

private static Stream GetS3Stream(string filename)
{
    AmazonS3Config config = new AmazonS3Config 
        {CommunicationProtocol = Protocol.HTTP};
    AmazonS3 client = AWSClientFactory.CreateAmazonS3Client(
        "sourceaccesskey",
        "sourcesecretacceskey", 
        config);
    string sourceBucketName = "sourcebucketname";

    GetObjectRequest request = new GetObjectRequest 
        {
            BucketName = sourceBucketName, 
            Key = filename
        };

    using (GetObjectResponse response = client.GetObject(request))
    {
        byte[] binaryData = 
        ReadFully(response.ResponseStream, -1);
        //ReadyFully from Jon Skeet's blog
        return new MemoryStream(binaryData);
    }
}

ReadFully方法由Jon Skeet充分解释。

1
我真的不认为有一种方法可以在账户之间转移。我知道唯一能做到这一点的协议是FXP。你可以向AWS提出请求,在将来可能会添加这个功能。

0

亚马逊有一个复制对象请求

AmazonS3Client client = new AmazonS3Client();

CopyObjectRequest request = new CopyObjectRequest {
      SourceBucket = "fromBucket",
      SourceKey = "fromFile",
      DestinationBucket = "toBucket",
      DestinationKey = "toFilename",
      CannedACL = S3CannedACL.BucketOwnerFullControl
 };

 CopyObjectResponse response = client.CopyObject(request);

2
但是这只适用于同一个S3账户内部,而不是两个不同的账户。 - Amr Elgarhy

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