2013-04-19 5 views
4

Je suis en train d'écrire une application et nous avons besoin de transférer des fichiers entre différents comptes s3, nous ne voulons pas enregistrer le fichier localement avant de le télécharger sur le compte s3 de destination.
Ainsi nous obtenons le flux de fichier source en utilisant ceci:Transférer un fichier d'un compte amazon s3 à un autre

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; 
} 

Et après que nous utilisons ce flux à télécharger sur la destination:

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); 

Mais sur la dernière ligne appel de la fonction « Envoyer » i Toujours obtenir cette erreur: Ce flux ne prend pas en charge les opérations de recherche.

Existe-t-il une façon différente de faire ce que j'essaie de faire? car il coud pas la bonne façon

+0

D'une certaine manière, lors de la diffusion, vous téléchargez tout de même fichier entier et rechargeant le même fichier, vous ne sauvegardez pas une bande passante ici, au lieu laisser enregistrer en tant que locale fichier, puis le télécharger. Inutile que vous voulez bloquer les tampons en mémoire ou bloquer les opérations réseau, ce n'est pas une bonne pratique. –

+0

Mon idée est d'obtenir quelques octets [buffersize] et de les transférer, puis d'en obtenir d'autres et de les transférer, comme ceci si 100 Go de fichiers sont transférés en même temps, mon disque dur ne sera pas plein. Corrigez-moi si je me trompe. –

+1

Pour de tels fichiers énormes, il échouera de toute façon, pour le transfert de fichiers de 100 Go, il y aura de nombreuses défaillances réseau, et pour le téléchargement, S3 a besoin d'une longueur de fichier pour pouvoir diviser les fichiers en plusieurs parties. Donc, sans d'abord télécharger le fichier entier, l'utilitaire de transfert ne fonctionnera pas. –

Répondre

1

Amazon a une copie Object Request

AmazonS3Client client = new AmazonS3Client(); 

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

CopyObjectResponse response = client.CopyObject(request); 
+0

mais cela fonctionne dans le même compte S3 pas 2 comptes différents. –

0

Je ne pense pas vraiment il y a un moyen de transférer entre les comptes. Le seul protocole que je sais pouvoir faire est FXP. Vous pouvez demander à AWS de le faire à l'avenir, ce serait une fonctionnalité intéressante.

2

Je suis tombé sur cette question et je publie l'approche que j'ai utilisée pour la résoudre. J'ai emprunté du code à Jon Skeet. Cela a fonctionné pour moi, mais je sais que c'est un peu maladroit et peut probablement être amélioré.

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); 
    } 
} 

méthode ReadFully expliqué entièrement par Jon Skeet

Questions connexes