2011-12-13 5 views
2

J'ai écrit une fonction en C# pour télécharger un fichier lorsque la copie vers un partage de fichiers ne fonctionne pas. Je remarque que tous les fichiers téléchargés sont environ 1.5-2x la taille de l'original et sont des fichiers invalides. Voici le code:Le téléchargement ftp est trop gros

public bool save_FTPUpload(FileInfo fi_attachment) 
{ 
    bool fileSaved = false; 
    string filename = fi_attachment.Name; 

    while (!fileSaved) 
    { 
     string file_ftpURI = string.Format("{0}/{1}", ftpURI, filename); 
     FtpWebRequest file_exist_request = (FtpWebRequest)FtpWebRequest.Create(file_ftpURI); 
     file_exist_request.Credentials = new NetworkCredential(ftp_user, ftp_pass); 
     file_exist_request.Method = WebRequestMethods.Ftp.GetFileSize; 
     try 
     { 
      FtpWebResponse response = (FtpWebResponse)file_exist_request.GetResponse(); 
     } 
     catch (WebException ex) 
     { 
      FtpWebResponse response = (FtpWebResponse)ex.Response; 
      if (response.StatusCode == 
       FtpStatusCode.ActionNotTakenFileUnavailable) 
      { 
       FtpWebRequest upload_request = (FtpWebRequest)FtpWebRequest.Create(file_ftpURI); 
       upload_request.Credentials = new NetworkCredential(ftp_user, ftp_pass); 

       upload_request.Method = WebRequestMethods.Ftp.UploadFile; 
       upload_request.UsePassive = true; 
       upload_request.UseBinary = true; 
       upload_request.KeepAlive = false; 

       StreamReader attachment = new StreamReader(fi_attachment.FullName); 
       byte[] attachmentData = Encoding.UTF8.GetBytes(attachment.ReadToEnd()); 
       upload_request.ContentLength = attachmentData.Length; 

       //Stream upload_request_stream = upload_request.GetRequestStream(); 
       using (Stream upload_request_stream = upload_request.GetRequestStream()) 
       { 
        upload_request_stream.Write(attachmentData, 0, attachmentData.Length); 
        upload_request_stream.Close(); 
       } 
       FtpWebResponse upload_response = (FtpWebResponse)upload_request.GetResponse(); 

       fileSaved = true; 
      } 
     } 
    } 
    return fileSaved; 
} 

Toute aide pour comprendre cela serait formidable.

+1

Vous faites un _lot_ dans ce bloc 'de catch'. Pourquoi? Quelle erreur manipulez-vous et comment essayez-vous de le gérer? En ... téléchargeant un fichier? – David

+0

@David - Le bloc catch est de vérifier une connexion FTP valide. Ramassé quelque part (probablement ici sur SO) –

+1

C'est vraiment quelque chose que vous aurez envie de réparer, alors. Je n'ai pas découvert la cause profonde du problème que vous signalez, mais l'utilisation d'un 'try/catch' pour le flux logique est _never_ une bonne idée. – David

Répondre

7

Vous devez copier le contenu du fichier en mode binaire, comme ceci:

var response = (FtpWebResponse)ex.Response; 
if (response.StatusCode == FtpStatusCode.ActionNotTakenFileUnavailable) { 
    FtpWebRequest upload_request = (FtpWebRequest)FtpWebRequest.Create(file_ftpURI); 
    upload_request.Credentials = new NetworkCredential(ftp_user, ftp_pass); 
    upload_request.Method = WebRequestMethods.Ftp.UploadFile; 
    upload_request.UsePassive = true; 
    upload_request.UseBinary = true; 
    upload_request.KeepAlive = false; 
    var attachment = File.Open(fi_attachment.FullName, FileMode.Open); 
    using (Stream upload_request_stream = upload_request.GetRequestStream()) { 
     attachment.CopyTo(upload_request_stream); 
     upload_request_stream.Close(); 
    } 
    var upload_response = (FtpWebResponse)upload_request.GetResponse(); 
    fileSaved = true; 
} 

Votre programme actuel, il se lit comme une très longue chaîne dans le codage UTF-8, ce qui explique probablement le changement taille du fichier.

+0

Genius !! A effectué immédiatement –

+1

+1. J'ai résolu mon problème avec des fichiers corrompus aussi. J'utilisais l'exemple MSDN, qui effectue le codage UTF-8 sans autre explication. Il convient de noter que le "CopyTo" -Method est .NET 4.0 et plus seulement. (Stumped moi pendant une minute parce que mon projet par défaut à .NET 3.5) –

+0

@StephanKeller C'est là que j'ai eu mon code aussi bien ... –

2

Pourquoi tout cela danser décoder un fichier puis le ré-encoder? Vous avez deux flux, n'est-ce pas? Vous voulez que le même fichier que vous avez sur le disque existe sur le serveur? Stream.CopyTo serait considérablement moins sujet aux erreurs.

Vous pouvez remplacer

   StreamReader attachment = new StreamReader(fi_attachment.FullName); 
       byte[] attachmentData = Encoding.UTF8.GetBytes(attachment.ReadToEnd()); 
       upload_request.ContentLength = attachmentData.Length; 

       //Stream upload_request_stream = upload_request.GetRequestStream(); 
       using (Stream upload_request_stream = upload_request.GetRequestStream()) 
       { 
        upload_request_stream.Write(attachmentData, 0, attachmentData.Length); 
        upload_request_stream.Close(); 
       } 

avec (du haut de ma tête)

using (var fs = File.OpenRead(fi_attachment.FullName)) 
using (Stream upload_request_stream = upload_request.GetRequestStream()) 
{ 
    fs.CopyTo(upload_request_stream); 
} 
Questions connexes