2010-08-26 16 views
10

Le code suivant est bon pour le téléchargement des fichiers texte, mais il ne parvient pas à télécharger des fichiers JPEG (pas complètement - le nom du fichier est bonne mais l'image est corrompue):Télécharger un fichier avec l'encodage via FTP en C#

private void up(string sourceFile, string targetFile) 
{ 
    try 
    { 
     string ftpServerIP = ConfigurationManager.AppSettings["ftpIP"]; 
     string ftpUserID = ConfigurationManager.AppSettings["ftpUser"]; 
     string ftpPassword = ConfigurationManager.AppSettings["ftpPass"]; 

     //string ftpURI = ""; 
     string filename = "ftp://" + ftpServerIP + "//" + targetFile; 
     FtpWebRequest ftpReq = (FtpWebRequest)WebRequest.Create(filename); 
     ftpReq.Method = WebRequestMethods.Ftp.UploadFile; 
     ftpReq.Credentials = new NetworkCredential(ftpUserID, ftpPassword); 

     StreamReader stream = new StreamReader(sourceFile); 
     Byte[] b = System.Text.Encoding.UTF8.GetBytes(stream.ReadToEnd()); 
     stream.Close(); 

     ftpReq.ContentLength = b.Length; 
     Stream s = ftpReq.GetRequestStream(); 
     s.Write(b, 0, b.Length); 
     s.Close(); 

     System.Net.FtpWebResponse ftpResp = (FtpWebResponse)ftpReq.GetResponse(); 
     MessageBox.Show(ftpResp.StatusDescription); 
    } 
    catch (Exception ex) 
    { 
     MessageBox.Show(ex.ToString()); 
    } 
} 

j'ai une autre solution qui peut télécharger un fichier:

private void Upload(string sourceFile, string targetFile) 
{ 
    string ftpUserID; 
    string ftpPassword; 
    string ftpServerIP; 
    ftpServerIP = ConfigurationManager.AppSettings["ftpIP"]; 
    ftpUserID = ConfigurationManager.AppSettings["ftpUser"]; 
    ftpPassword = ConfigurationManager.AppSettings["ftpPass"]; 
    FileInfo fileInf = new FileInfo(sourceFile); 
    FtpWebRequest reqFTP; 

    // Create FtpWebRequest object from the Uri provided 
    reqFTP = (FtpWebRequest)(FtpWebRequest.Create(new Uri("ftp://" + ftpServerIP + "//" + targetFile))); 

    // Provide the WebPermission Credintials 
    reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword); 

    // Bypass default lan settings 
    reqFTP.Proxy = null; 

    // By default KeepAlive is true, where the control connection is not closed 
    // after a command is executed. 
    reqFTP.KeepAlive = false; 

    // Specify the command to be executed. 
    reqFTP.Method = WebRequestMethods.Ftp.UploadFile; 

    // Specify the data transfer type. 
    reqFTP.UseBinary = true; 

    // Notify the server about the size of the uploaded file 
    reqFTP.ContentLength = fileInf.Length; 

    // The buffer size is set to 2kb 
    int buffLength = 2048; 
    Byte[] buff; 
    buff = new byte[buffLength]; 
    int contentLen; 

    // Opens a file stream (System.IO.FileStream) to read the file to be uploaded 
    FileStream fs = fileInf.OpenRead(); 

    try 
    { 
     // Stream to which the file to be upload is written 
     Stream strm = reqFTP.GetRequestStream(); 

     // Read from the file stream 2kb at a time 
     long filesize = fs.Length; 
     int i=0; 
     contentLen = fs.Read(buff, 0, buffLength); 

     // Till Stream content ends 
     while (contentLen != 0) 
     { 
      Application.DoEvents(); 
      // Write Content from the file stream to the FTP Upload Stream 
      strm.Write(buff, 0, contentLen); 
      contentLen = fs.Read(buff, 0, buffLength); 
      i = i + 1; 
      //Double percentComp = (i * buffLength) * 100/filesize; 
      //ProgressBar1.Value = (int)percentComp; 
     } 

     // Close the file stream and the Request Stream 
     strm.Close(); 
     fs.Close(); 
    } 

    catch (Exception ex) 
    { 
     MessageBox.Show(ex.Message, "Upload Error"); 
    } 
} 

mais ici j'ai le problème inverse - l'image est bonne, mais le nom de fichier est corrompu.

Je sais qu'il est à cause de l'encodage, mais je ne sais pas comment faire le tableau d'octets ont l'encodage désiré ...

+0

Je ne peux pas comprendre, pourquoi auriez-vous un problème avec le nom de fichier corrompu avec le deuxième code, mais pas avec le premier code. Et pourquoi la réponse acceptée aiderait-elle? Dans tous les cas, vous spécifiez exactement le même nom de fichier. –

+0

Je suis désolé Martin. J'ai écrit la question il y a une dizaine d'années. Je ne me souviens pas quel était le problème et quelle était la solution. Je pense que vous devriez ouvrir un nouveau fil avec votre propre question. – Asaf

+0

Je n'ai pas de question, je me demande juste quel est le point de votre question et la réponse :) –

Répondre

19

Essayez ce bit:

private static void up(string sourceFile, string targetFile) 
{    
    try 
    { 
     string ftpServerIP = ConfigurationManager.AppSettings["ftpIP"]; 
     string ftpUserID = ConfigurationManager.AppSettings["ftpUser"]; 
     string ftpPassword = ConfigurationManager.AppSettings["ftpPass"]; 
     ////string ftpURI = ""; 
     string filename = "ftp://" + ftpServerIP + "//" + targetFile; 
     FtpWebRequest ftpReq = (FtpWebRequest)WebRequest.Create(filename); 
     ftpReq.UseBinary = true; 
     ftpReq.Method = WebRequestMethods.Ftp.UploadFile; 
     ftpReq.Credentials = new NetworkCredential(ftpUserID, ftpPassword); 

     byte[] b = File.ReadAllBytes(sourceFile); 

     ftpReq.ContentLength = b.Length; 
     using (Stream s = ftpReq.GetRequestStream()) 
     { 
      s.Write(b, 0, b.Length); 
     } 

     FtpWebResponse ftpResp = (FtpWebResponse)ftpReq.GetResponse(); 

     if (ftpResp != null) 
     { 
      MessageBox.Show(ftpResp.StatusDescription); 
     } 
    } 
    catch (Exception ex) 
    { 
     MessageBox.Show(ex.ToString()); 
    } 
} 
+1

Pourquoi 's.Write (b, 0, b.Length);' dans un bloc 'using'? –

+4

Parce que 'Stream s' est une ressource' IDisposable'. –

+0

Ici, la différence magique est également 'byte [] b = File.ReadAllBytes (sourceFile);' comparez à d'autres exemples trouvés 'Encoding.UTF8.GetBytes (stream.ReadToEnd())'. –

2

Vous devez utiliser un Stream pour lire les fichiers binaires, pas un StreamReader . StreamReader est conçu pour lire des fichiers texte seulement.

+0

J'ai essayé de jouer avec le code pendant 3 heures maintenant, et j'ai aussi trouvé le streamReader qui vient avec l'encodage (en le constructeur) - mais je ne pouvais pas comprendre comment utiliser ni le streamreader ni les objets stream. Les flux sont comme une boîte noire pour moi :( – Asaf

2

Dans votre premier exemple de code, activez le transfert binaire: FtpWebRequest.UseBinary = true. Sinon, il convertira ce qu'il pense être des fins de ligne textuelles entre les différentes conventions de la plate-forme (mais font en réalité partie de l'image).

+0

Il doit y avoir quelque chose d'autre manquant ... J'ai ajouté la ligne que vous me jeu - mais rien n'a changé – Asaf

+0

Oui, voir la réponse de Mark: vous essayez de lire le fichier comme texte UTF8 .Dissiper le ** StreamReader ** et lire les octets directement à partir du flux, par ex. avec ** Stream.Read() **. –

0

System.Text.Encoding.UTF8.GetBytes(stream.ReadToEnd());

Ne le faites pas à moins que le texte sont le contenu de votre flux. Changez votre fonction pour accepter un paramètre booléen "binaire", et utilisez cette dernière méthode de travail si cet indicateur est défini.

2

Votre deuxième extrait le fait de la bonne façon. Il utilise FileStream, pas StreamReader. StreamReader est uniquement adapté aux fichiers texte.