36 votes

Comment télécharger des fichiers sur Amazon S3 (SDK officiel) d'une taille supérieure à 5 Mo (environ)?

Je suis l'aide de la dernière version officielle d'Amazon S3 SDK (1.0.14.1) pour créer un outil de sauvegarde. Jusqu'à présent, tout fonctionne correctement si la taille du fichier je suis le téléchargement est en dessous de 5 MO, mais si l'un des fichiers est au-dessus de 5 MO, le téléchargement échoue avec l'exception suivante:

Système.Net.WebException: La demande a été abandonnée: La demande a été annulée. ---> Système.IO.IOException: Impossible de fermer le flux jusqu'à ce que tous les octets sont écrit. au Système.Net.ConnectStream.CloseInternal(Boolean internalCall, Boolean abandon) --- À la fin de l'exception interne trace de la pile --- au Amazon.S3.AmazonS3Client.ProcessRequestError(String nomaction, HttpWebRequest demande, WebException nous, HttpWebResponse errorResponse, Chaîne requestAddr, WebHeaderCollection& respHdrs, Type t) au Amazon.S3.AmazonS3Client.Invoquer[T](S3Request userRequest) à Amazon.S3.AmazonS3Client.PutObject(PutObjectRequest demande) BackupToolkit.S3Module.UploadFile(String sourceFileName, Chaîne destinationFileName) dans W:\code\AutoBackupTool\BackupToolkit\S3Module.cs:ligne 88 à BackupToolkit.S3Module.UploadFiles(String sourceDirectory) dans W:\code\AutoBackupTool\BackupToolkit\S3Module.cs:ligne 108

Note: 5 MO est à peu près la limite de l'échec, il peut être légèrement inférieure ou quelque chose de plus élevé

Je suis en supposant que la connexion est le moment de sortir et le flux est automatiquement fermé avant l'upload de fichier est terminée.

J'ai essayé de trouver un moyen de définir un délai long (mais je ne trouve pas l'option en AmazonS3 ou AmazonS3Config).

Toutes les idées sur la façon d'augmenter le délai d'attente (comme une application à l'échelle de réglage, je peux l'utiliser) ou bien est-il pas lié à un problème de délai d'attente?


Code:

var s3Client = AWSClientFactory.CreateAmazonS3Client(AwsAccessKey, AwsSecretKey);

var putObjectRequest = new PutObjectRequest {

    BucketName            = Bucket,
    FilePath              = sourceFileName,
    Key                   = destinationFileName,
    MD5Digest             = md5Base64,
    GenerateMD5Digest     = true
};

using (var upload = s3Client.PutObject(putObjectRequest)) {  }

42voto

InvertedAcceleration Points 2258

Mise à jour de réponse:

J'ai récemment mis à jour un de mes projets qui utilise les Amazon AWS .NET SDK (pour la version 1.4.1.0) et dans cette version il y a deux améliorations qui n'existait pas quand j'ai écrit la réponse originale à cette question ici.

  1. Vous pouvez maintenant configurer Timeout de -1 ayant une infinité de limite de temps pour la mettre en fonctionnement.
  2. Il y a maintenant un supplément de propriété sur PutObjectRequest appelés ReadWriteTimeout qui peut être réglé (en millisecondes) en attente sur le flux de lecture/écriture de niveau d'opposition à l'ensemble de l'opération de placement niveau.

Donc, mon code ressemble maintenant à ceci:

var putObjectRequest = new PutObjectRequest {

    BucketName            = Bucket,
    FilePath              = sourceFileName,
    Key                   = destinationFileName,
    MD5Digest             = md5Base64,
    GenerateMD5Digest     = true,
    Timeout               = -1,
    ReadWriteTimeout      = 300000     // 5 minutes in milliseconds
};

Réponse originale à cette question:


J'ai réussi à trouver la réponse...

Avant de poster la question que j'avais exploré AmazonS3 et AmazonS3Config mais pas PutObjectRequest.

À l'intérieur d' PutObjectRequest il y a un Timeout de la propriété (défini en millisecondes). J'ai utilisé avec succès cette pour télécharger les fichiers les plus grands (remarque: la valeur 0 n'est pas supprimer le délai d'attente, vous devez spécifier un nombre positif de millisecondes... je suis allé pour 1 heure).

Cela fonctionne très bien:

var putObjectRequest = new PutObjectRequest {

    BucketName            = Bucket,
    FilePath              = sourceFileName,
    Key                   = destinationFileName,
    MD5Digest             = md5Base64,
    GenerateMD5Digest     = true,
    Timeout               = 3600000
};

10voto

Nick Randell Points 4133

J'ai eu des problèmes similaires à ceux-ci et j'ai commencé à utiliser la classe TransferUtility pour effectuer des téléchargements en plusieurs parties.

Pour le moment, ce code fonctionne. J'ai eu des problèmes quand le délai d'attente était trop bas!

                 var request = new TransferUtilityUploadRequest()
                .WithBucketName(BucketName)
                .WithFilePath(sourceFile.FullName)
                .WithKey(key)
                .WithTimeout(100 * 60 * 60 * 1000)
                .WithPartSize(10 * 1024 * 1024)
                .WithSubscriber((src, e) =>
                {
                    Console.CursorLeft = 0;
                    Console.Write("{0}: {1} of {2}    ", sourceFile.Name, e.TransferredBytes, e.TotalBytes);
                });
            utility.Upload(request);
 

Tandis que je tape ceci, un téléchargement de 4 Go est en cours et il est déjà plus avancé que jamais!

6voto

user369142 Points 365

Nick Randell a eu la bonne idée à ce sujet. En plus de son message, voici un autre exemple de gestion alternative des événements et une méthode permettant de compléter le pourcentage du fichier téléchargé:

         private static string WritingLargeFile(AmazonS3 client, int mediaId, string bucketName, string amazonKey, string fileName, string fileDesc, string fullPath)
    {
        try
        {

            Log.Add(LogTypes.Debug, mediaId, "WritingLargeFile: Create TransferUtilityUploadRequest");
            var request = new TransferUtilityUploadRequest()
                .WithBucketName(bucketName)
                .WithKey(amazonKey)
                .WithMetadata("fileName", fileName)
                .WithMetadata("fileDesc", fileDesc)
                .WithCannedACL(S3CannedACL.PublicRead)
                .WithFilePath(fullPath)
                .WithTimeout(100 * 60 * 60 * 1000) //100 min timeout
                .WithPartSize(5 * 1024 * 1024); // Upload in 5MB pieces 

            request.UploadProgressEvent += new EventHandler<UploadProgressArgs>(uploadRequest_UploadPartProgressEvent);

            Log.Add(LogTypes.Debug, mediaId, "WritingLargeFile: Create TransferUtility");
            TransferUtility fileTransferUtility = new TransferUtility(ConfigurationManager.AppSettings["AWSAccessKey"], ConfigurationManager.AppSettings["AWSSecretKey"]);

            Log.Add(LogTypes.Debug, mediaId, "WritingLargeFile: Start Upload");
            fileTransferUtility.Upload(request);

            return amazonKey;
        }
        catch (AmazonS3Exception amazonS3Exception)
        {
            if (amazonS3Exception.ErrorCode != null &&
                (amazonS3Exception.ErrorCode.Equals("InvalidAccessKeyId") ||
                amazonS3Exception.ErrorCode.Equals("InvalidSecurity")))
            {
                Log.Add(LogTypes.Debug, mediaId, "Please check the provided AWS Credentials.");
            }
            else
            {
                Log.Add(LogTypes.Debug, mediaId, String.Format("An error occurred with the message '{0}' when writing an object", amazonS3Exception.Message));
            }
            return String.Empty; //Failed
        }
    }

    private static Dictionary<string, int> uploadTracker = new Dictionary<string, int>();
    static void uploadRequest_UploadPartProgressEvent(object sender, UploadProgressArgs e)
    {
        TransferUtilityUploadRequest req = sender as TransferUtilityUploadRequest;          
        if (req != null)
        {
            string fileName = req.FilePath.Split('\\').Last();
            if (!uploadTracker.ContainsKey(fileName))
                uploadTracker.Add(fileName, e.PercentDone);

            //When percentage done changes add logentry:
            if (uploadTracker[fileName] != e.PercentDone)
            {
                uploadTracker[fileName] = e.PercentDone;
                Log.Add(LogTypes.Debug, 0, String.Format("WritingLargeFile progress: {1} of {2} ({3}%) for file '{0}'", fileName, e.TransferredBytes, e.TotalBytes, e.PercentDone));
            }
        }

    }

    public static int GetAmazonUploadPercentDone(string fileName)
    {
        if (!uploadTracker.ContainsKey(fileName))
            return 0;

        return uploadTracker[fileName];
    }
 

1voto

docesam Points 84

Voir cette rubrique ici Comment télécharger un fichier sur amazon S3 super facilement en utilisant c #, y compris un projet de démonstration à télécharger. il est de haut niveau avec AWS sdk .net 3.5 (et supérieur), il peut être utilisé avec le code suivant:

     // preparing our file and directory names
        string fileToBackup = @"d:\mybackupFile.zip" ; // test file
        string myBucketName = "mys3bucketname"; //your s3 bucket name goes here
        string s3DirectoryName = "justdemodirectory";
        string s3FileName = @"mybackupFile uploaded in 12-9-2014.zip";
        AmazonUploader myUploader = new AmazonUploader();
        myUploader.sendMyFileToS3(fileToBackup, myBucketName, s3DirectoryName, s3FileName);
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X