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