之前介紹過使用System.Net.WebClient類別進行FTP傳檔的精簡寫法,今天發現一個問題。

某個Windows IIS FTP網站開放使用特定帳號user1登入後上傳或下載檔案,使用IE以 ftp:// ftp_ip_address/user1/test.txt的方式可以順利下檔案,但執行以下程式:

using System;
using System.IO;
using System.Threading;
using System.Net;
 
public class CSharpLab
{
    public static void Test()
    {
        WebClient wc = new WebClient();
        wc.Credentials = new NetworkCredential("user1", "****");
        string s = wc.DownloadString("ftp://172.28.1.1/user1/test.txt");
        Console.WriteLine(s + "\nDone!");
    }
}

卻會傳回錯誤:
The remote server returned an error: (550) File unavailable (e.g., file not found, no access).

同事發現,若將URL改成ftp:// 172.28.1.1/test.txt,反而可以成功下載。推測應是WebClient在處理FTP位址的邏輯中,會預設加上帳號名稱(例: user1)成為路徑的一部分

配合IIS FTP的Log,印證此點:

#Software: Microsoft Internet Information Services 6.0
#Version: 1.0
#Date: 2011-03-25 02:56:53
#Fields: time c-ip cs-method cs-uri-stem sc-status sc-win32-status 
02:56:53 172.28.1.1 [1]USER user1 331 0
02:56:54 172.28.1.1 [1]PASS - 230 0
02:57:26 172.28.1.1 [1]QUIT - 257 0
02:58:09 172.28.1.1 [2]USER user1 331 0
02:58:09 172.28.1.1 [2]PASS - 230 0
/* 下載ftp:// 172.28.1.1/user1/test.txt */ 
02:58:09 172.28.1.1 [2]CWD /user1/user1 550 2
02:59:05 172.28.1.1 [4]USER user1 331 0
02:59:05 172.28.1.1 [4]PASS - 230 0
/* 下載ftp:// 172.28.1.1/fodler1/foler2/test.txt */
02:59:05 172.28.1.1 [4]CWD /user1/folder1/folder2 550 3 
02:59:17 172.28.1.1 [3]USER user1 331 0
02:59:17 172.28.1.1 [3]PASS - 230 0
/* 下載ftp:// 172.28.1.1/test.txt */ 
02:59:17 172.28.1.1 [3]CWD /user1 250 0
02:59:17 172.28.1.1 [3]sent /user1/test.txt 226 0
02:59:35 172.28.1.1 [3]closed - 426 1341
03:45:39 172.28.1.1 [6]USER user1 331 0
03:45:39 172.28.1.1 [6]PASS - 230 0
/* 下載ftp:// 172.28.1.1/../test.txt */ 
03:45:39 172.28.1.1 [6]CWD /user1 250 0
03:45:39 172.28.1.1 [6]sent /user1/a.txt 550 2

由Log來看,WebClient會在以非匿名方式連線FTP傳檔時,先使用CWD切換路徑,切換時一律強制加上使用者帳號,造成了我們所觀察到的現象。最後一個測試用".."則變成CWD /user1,".."被無視,無法切至上層目錄。

【結論】
當System.Net.WebClient以特定身分認證(例如: user1)連線ftp:// ftpserver/file.ext方式傳檔時,會在file.ext路徑前方冠上"/user1/"(且無法用".."切到user1目錄的上層),若檔案在/user1/test.txt,URL應改為ftp:// ftpserver/test.txt方可正確對映。

[2012-08-22更新]FTP URL其實可以指定絕對路徑


Comments

# by jerryH

".."會被無視,無法切至上層目錄。 若有user2 是不是就無法用 /* 下載ftp:// 172.28.1.1/../user2/test2.txt */ 就不能用WebClient嗎?

# by Jeffrey

to jerryH, 依我的理解,WebClient假設你會用userX帳號登入來存取/userX/目錄下的檔案,如果硬要用user1登入,存取不在/user1/下的檔案(指非/user1/*, /user1/subFolder/*等隸屬關係,例如: /user2/blah.txt),就會因目錄無法切換而失敗。

# by nicole

謝謝helpful

Post a comment