2010-06-14 14 views
8

Lưu ý: do cơ chế chống spam, tôi đã buộc phải thay thế phần đầu của Uris từ ftp: // thành ftp.Không thể đổi tên tệp bằng các phương thức ftp khi thư mục người dùng hiện tại khác với thư mục gốc

Tôi gặp sự cố sau. Tôi phải tải lên tập tin với phương pháp C# ftp và sau đó đổi tên nó. Dễ dàng, phải không? :)

Ok, chúng ta hãy nói máy chủ ftp của tôi là như thế này:

ftp.contoso.com

và sau khi đăng nhập, thư mục hiện hành được thiết lập để:

users/name

Vì vậy, những gì tôi đang cố gắng để đạt được là đăng nhập, tải tệp lên thư mục hiện tại dưới dạng tệp.ext.tmp và sau khi tải lên thành công, hãy đổi tên tệp thành tệp.ext

Toàn bộ khó khăn là, như tôi đoán, để đặt đúng yêu cầu Uri cho FtpWebRe nhiệm vụ.

MSDN khẳng định:

The URI may be relative or absolute. If the URI is of the form " ftp://contoso.com/%2fpath " (%2f is an escaped '/'), then the URI is absolute, and the current directory is /path. If, however, the URI is of the form " ftp://contoso.com/path ", first the .NET Framework logs into the FTP server (using the user name and password set by the Credentials property), then the current directory is set to UserLoginDirectory/path.

Ok, vì vậy tôi tải lên tập tin với URI sau:

ftp.contoso.com/file.ext.tmp

Tuyệt vời, các vùng đất tập tin mà tôi muốn nó phải là: trong thư mục "người dùng/tên "

Bây giờ, tôi muốn đổi tên tệp, vì vậy tôi tạo yêu cầu web theo dõi Uri:

ftp.contoso.com/file.ext.tmp

và chỉ định đổi tên để tham số như:

file.ext

và điều này mang lại cho tôi 550 lỗi: không tìm thấy file, không có quyền vv

tôi truy tìm này trong Microsoft Network Monitor và nó đã cho tôi:

Command: RNFR, Rename from
CommandParameter: /file.ext.tmp
Ftp: Response to Port 53724, '550 File /file.ext.tmp not found'

như thể đang tìm tệp trong thư mục gốc - không nằm trong thư mục hiện tại.

tôi đổi tên các tập tin bằng tay sử dụng Total Commander và sự khác biệt duy nhất là CommandParameter là không có dấu gạch chéo đầu tiên:

CommandParameter: file.ext.tmp

Tôi có thể đổi tên thành công tệp tin bằng cách cung cấp sau đây tuyệt đối URI:

ftp.contoso.com/%2fusers/%2fname/file.ext.tmp

nhưng tôi không thích cách tiếp cận này, vì tôi sẽ phải biết tên thư mục của người dùng hiện tại. Nó có thể có thể được thực hiện bằng cách sử dụng WebRequestMethods.Ftp.PrintWorkingDirectory, nhưng nó bổ sung thêm sự phức tạp (gọi phương thức này để lấy tên thư mục, sau đó kết hợp các đường dẫn để tạo URI thích hợp).

Điều tôi không hiểu là tại sao URI ftp.contoso.com/file.ext.tmp lại tốt để tải lên chứ không phải để đổi tên? Am i thiếu cái gì ở đây?

Dự án được đặt thành .NET 4.0, được mã hóa trong Visual Studio 2010.

Chỉnh sửa

Ok, tôi đặt đoạn mã.

Xin lưu ý rằng máy chủ lưu trữ ftp, tên người dùng và mật khẩu sẽ được điền. Đối với mẫu này để làm việc - đó là, tạo ra một lỗi - thư mục người dùng phải khác với root ("pwd" -Command nên trả lại một cái gì đó khác với "/")

class Program 
{ 
    private const string fileName = "test.ext"; 
    private const string tempFileName = fileName + ".tmp"; 
    private const string ftpHost = "127.0.0.1"; 
    private const string ftpUserName = "anonymous"; 
    private const string ftpPassword = ""; 
    private const int bufferSize = 524288; 

    static void Main(string[] args) 
    { 
     try 
     { 
      string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), fileName); 

      if (!File.Exists(path)) 
       File.WriteAllText(path, "FTP RENAME SAMPLE"); 

      string requestUri = "ftp://" + ftpHost + "/" + tempFileName; 

      //upload 

      FtpWebRequest uploadRequest = (FtpWebRequest)WebRequest.Create(requestUri); 
      uploadRequest.UseBinary = true; 
      uploadRequest.UsePassive = true; 
      uploadRequest.Credentials = new NetworkCredential(ftpUserName, ftpPassword); 
      uploadRequest.KeepAlive = true; 
      uploadRequest.Method = WebRequestMethods.Ftp.UploadFile; 

      Stream requestStream = null; 
      FileStream localFileStream = null; 


      localFileStream = File.OpenRead(path); 
      requestStream = uploadRequest.GetRequestStream(); 
      byte[] buffer = new byte[bufferSize]; 

      int readCount = localFileStream.Read(buffer, 0, bufferSize); 
      long bytesSentCounter = 0; 

      while (readCount > 0) 
      { 
       requestStream.Write(buffer, 0, readCount); 
       bytesSentCounter += readCount; 
       readCount = localFileStream.Read(buffer, 0, bufferSize); 
       System.Threading.Thread.Sleep(100); 
      } 

      localFileStream.Close(); 
      requestStream.Close(); 

      FtpWebResponse response = (FtpWebResponse)uploadRequest.GetResponse(); 
      FtpStatusCode code = response.StatusCode; 
      string description = response.StatusDescription; 
      response.Close(); 

      if (code == FtpStatusCode.ClosingData) 
       Console.WriteLine("File uploaded successfully"); 

      //rename 

      FtpWebRequest renameRequest = (FtpWebRequest)WebRequest.Create(requestUri); 
      renameRequest.UseBinary = true; 
      renameRequest.UsePassive = true; 
      renameRequest.Credentials = new NetworkCredential(ftpUserName, ftpPassword); 
      renameRequest.KeepAlive = true; 
      renameRequest.Method = WebRequestMethods.Ftp.Rename; 
      renameRequest.RenameTo = fileName; 

      try 
      { 

       FtpWebResponse renameResponse = (FtpWebResponse)renameRequest.GetResponse(); 

       Console.WriteLine("Rename OK, status code: {0}, rename status description: {1}", response.StatusCode, response.StatusDescription); 

       renameResponse.Close(); 
      } 
      catch (WebException ex) 
      { 
       Console.WriteLine("Rename failed, status code: {0}, rename status description: {1}", ((FtpWebResponse)ex.Response).StatusCode, 
        ((FtpWebResponse)ex.Response).StatusDescription); 
      } 

     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.ToString()); 
     } 
     finally 
     { 
      Console.ReadKey(); 
     } 
    } 
} 
+1

Bạn đã đưa ra một phạm vi rộng lớn về vấn đề của mình (có thể quá rộng?), Nhưng điều thực sự hữu ích là hiển thị mã của bạn, cụ thể là phần bạn đổi tên. Lưu ý rằng thông thường bạn không cần phải tiền tố tên site khi thực hiện FTP. – Abel

Trả lời

4

C#

using System.Net; 
using System.IO; 

Đổi tên ảnh Tên ảnh về chức năng FTP server

C#

private void RenameFileName(string currentFilename, string newFilename) 
    { 
     FTPSettings.IP = "DOMAIN NAME"; 
     FTPSettings.UserID = "USER ID"; 
     FTPSettings.Password = "PASSWORD"; 
     FtpWebRequest reqFTP = null; 
     Stream ftpStream = null ; 
     try 
     { 

      reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + FTPSettings.IP + "/" + currentFilename)); 
      reqFTP.Method = WebRequestMethods.Ftp.Rename; 
      reqFTP.RenameTo = newFilename; 
      reqFTP.UseBinary = true; 
      reqFTP.Credentials = new NetworkCredential(FTPSettings.UserID, FTPSettings.Password); 
      FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse(); 
      ftpStream = response.GetResponseStream(); 
      ftpStream.Close(); 
      response.Close(); 
     } 
     catch (Exception ex) 
     { 
      if (ftpStream != null) 
      { 
       ftpStream.Close(); 
       ftpStream.Dispose(); 
      } 
      throw new Exception(ex.Message.ToString()); 
     } 
    } 

    public static class FTPSettings 
    { 
     public static string IP { get; set; } 
     public static string UserID { get; set; } 
     public static string Password { get; set; } 
    } 
7

tôi đã gặp phải một vấn đề tương tự. Vấn đề là FtpWebRequest (không chính xác) prepends '/' để đổi tên yêu cầu, như có thể thấy từ nhật ký này (tải lên & đổi tên):

URL: 
    http://127.0.0.1/Test.txt 
FTP log: 
    STOR Test.txt.part 
    RNFR /Test.txt.part 
    RNTO /Test.txt 

Xin lưu ý rằng vấn đề này chỉ xảy ra khi bạn đang tải lên vào thư mục gốc danh mục. Nếu bạn thay đổi URL thành http://127.0.0.1/path/Test.txt, thì mọi thứ sẽ hoạt động tốt.

Giải pháp của tôi cho vấn đề này là sử dụng% 2E (dot) là đường dẫn:

URL: 
    http://127.0.0.1/%2E/Test.txt 
FTP log: 
STOR ./Test.txt.part 
RNFR ./Test.txt.part 
RNTO ./Test.txt 

Bạn phải URL mã hóa dấu chấm, nếu không FtpWebRequest sẽ đơn giản hóa đường dẫn "/./" thành "/".

+0

Cảm ơn bạn. Điều này cố định một vấn đề NET FTP khá mơ hồ đối với tôi. Không có giải pháp nào khác hiệu quả. –