2010-08-26 61 views
10

下面的代碼是好的上傳文本文件,但它不能上傳JPEG文件(不完全 - 文件名是好的,但圖像被損壞):上傳在C#中使用FTP編碼文件

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

我有另一種解決方案,可以上傳文件:

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

但在這裏我有相反的問題 - 畫面是好的,但文件名被破壞。

我知道那是因爲編碼的,但我不知道如何使字節數組具有所需的編碼...

+0

我不明白,爲什麼你會有第二個代碼損壞的文件名的問題,但與第一個代碼沒有關係。爲什麼接受的答案會對此有所幫助。在所有情況下,您都以完全相同的方式指定文件名。 – 2017-10-25 06:51:20

+0

對不起馬丁。我十年前寫過這個問題。我不記得是什麼問題和解決方案。我想你應該用自己的問題開一個新的主題。 – Asaf 2017-10-25 07:01:54

+0

我沒有問題,我只是想知道你的問題和答案是什麼:) – 2017-10-25 07:16:09

回答

19

試試這個位:

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

爲什麼's.Write(b,0,b.Length);'在'using'塊中? – 2013-09-26 18:04:14

+4

因爲'Stream s'是一個'IDisposable'資源。 – 2013-09-26 18:05:20

+0

這裏,神奇的區別也是'byte [] b = File.ReadAllBytes(sourceFile);'比較其他例子找到的又名'Encoding.UTF8.GetBytes(stream.ReadToEnd())'。 – 2017-05-20 05:25:04

2

你應該使用Stream讀取二進制文件,而不是一個StreamReaderStreamReader僅用於讀取文本文件。

+0

我嘗試了3小時的代碼,並且我還發現了帶有編碼的streamReader(在構造函數) - 但我無法理解如何使用streamreader和流對象。 流對我來說就像一個黑盒子:( – Asaf 2010-08-26 15:08:45

2

在您的第一個代碼示例中,啓用二進制傳輸:FtpWebRequest.UseBinary = true。否則,它會轉換它認爲是各種平臺約定之間的文本行尾(但實際上是圖像的一部分)。

+0

必須有其他的東西丟失......我添加了你的遊戲我 - 但沒有任何改變 – Asaf 2010-08-26 15:20:54

+0

是的,看到馬克的答案:你試圖讀取文件爲UTF8文本。拋棄** StreamReader **並直接從流中讀取字節,例如與** Stream.Read()**。 – 2010-08-26 22:16:10

0

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

不這樣做,除非你流的內容是文本。改變你的函數接受一個布爾參數「二進制」,並使用後者,工作方法,如果該標誌被設置。

2

你的第二個片段是正確的。它使用FileStream,而不是StreamReader。 StreamReader僅適用於文本文件。使用HTTP

你需要在空或沒有設置代理時請求的FTP命令不支持: