【问题标题】:URI whitespaces are converted to "%20" with WebClient.DownloadData使用 WebClient.DownloadData 将 URI 空格转换为“%20”
【发布时间】:2018-01-02 18:09:55
【问题描述】:

我正在尝试使用 WebClient 类通过 FTP 下载文件。 问题是,FTP 服务器上包含文件路径的目录之一包含空格。

而且,即使我的 URI 字符串有空格,但在使用 DownloadData 方法时,它们都会自动转换为“%20”,因此找不到目录,下载失败。

我的问题是:有没有办法强制 WebClient 不将我的空格转换为 %20 ?

这是我的代码:

using (WebClient request = new WebClient())
{
    request.Credentials = new NetworkCredential("login", "password");
    string url = ("ftp://XXX.XXX.XX.XXX:21/root/folder1/folder with spaces/pic1.jpg");
    byte[] fileData = request.DownloadData(url);
    using (FileStream file = File.Create(localpath))
    {
        file.Write(fileData, 0, fileData.Length);
        file.Close();
    }
}

使用 Wireshark,这是我的网络日志:

Request: USER login
Response: 331 Please specify the password
Request: PASS password
Response: 230 Login successful
Request: OPTS utf8 on
Response: 200 Always in UTF8 mode.
Request: PWD
Response: 257 "/home/login"
Request: CWD home/login/root/folder1/folder%20with%20spaces/
Response: 550 Failed to change directory 

尝试下载文件夹 1 的日志(请注意,CWD 没有失败,我只是收到一个错误,因为它需要的是文件而不是文件夹):

Response: 230 Login successful
Request: OPTS utf8 on
Response: 200 Always in UTF8 mode.
Request: PWD
Response: 257 "/home/login"
Request: CWD home/login/root/
Response: 250 Directory successfully changed
Request: RETR folder1
Response: 550 Failed to open file.

使用FileZilla下载pic1.jpg的日志(注意区别是文件路径中没有%20):

Response: 230 Login successful
Request: OPTS UTF8 on
Response: 200 Always in UTF8 mode.
Request: CWD home/login/root/folder1/folder with spaces/
Response: 250 Directory successfully changed
Request: RETR pic1.jpg
Response: 150 Opening BINARY mode data connection for pic1.jpg
Response: 226 Transfer complete.

【问题讨论】:

  • 您可以在将值用作文件路径之前对值进行 URL 解码。
  • 告诉我们.NET network log file
  • filePath 的值是什么? + 你遇到了什么异常?
  • filePath is "/folder1/folder with spaces/picture.jpg" 异常是“WebException: Server returned an error: 550 Failed to change directory”
  • 如果您只是将示例代码中的filePath 替换为包含空格的实际路径会更明显。

标签: c# download ftp


【解决方案1】:

如果您需要访问与主文件夹无关的路径,则需要使用两个斜杠:

string url = "ftp://XXX.XXX.XX.XXX:21//root/folder1/folder with spaces/pic1.jpg";

或类似的相对路径:

string url = "ftp://XXX.XXX.XX.XXX:21/../../root/folder1/folder with spaces/pic1.jpg";

(问题与空格无关)

【讨论】:

  • 我也想过这个问题,但我可以访问 root 和 folder1 就好了,我尝试访问另一张具有类似路径(但没有任何空格)的图片,它的工作就像一个魅力......
  • 发布访问folder1的日志文件。 + 你可以使用任何(甚至是 GUI)FTP 客户端访问folder with spaces 吗?
  • 是的,我可以使用 FileZilla 或我的浏览器访问该文件夹。这是日志:-------- 请求:PWD 响应:257 "/home/login" 请求:CWD home/login/root/ 响应:250 目录成功更改请求:RETR 文件夹1 响应:550 无法打开文件. -------- 我仍然收到错误,因为它是文件夹而不是文件,但重要的是 CWD 没有失败。
  • 将日志编辑到您的问题中 + 向我们展示两个文件夹的 FileZilla 日志文件。
  • 完成。我没有记录尝试使用 FileZilla 下载 folder1 的日志,因为它会自动递归下载所有文件,因此无法进行比较
【解决方案2】:

您可以尝试使用Uri(string, bool) 手动创建您的Uri 吗?

using (WebClient request = new WebClient())
{
    request.Credentials = new NetworkCredential("login", "password");
    string url = "ftp://XXX.XXX.XX.XXX:21/root/folder1/folder with spaces/pic1.jpg";
    var uri = new Uri(url, true);
    byte[] fileData = request.DownloadData(uri);
    using (FileStream file = File.Create(localpath))
    {
        file.Write(fileData, 0, fileData.Length);
        file.Close();
    }
}

请注意,Uri(string, bool) 已被声明为已过时,因此可能会在某个时候将其从框架中删除。

【讨论】:

    【解决方案3】:

    如果您没有使用 WebClient.DownloadFile 的原因是什么?

    using (WebClient request = new WebClient())
    {
       request.Credentials = new NetworkCredential("login", "password");
       string url = ("ftp://XXX.XXX.XX.XXX:21/root" + filePath);
       request.DownloadFile(url, localpath);
     }
    

    【讨论】:

    • 这如何回答这个问题? OP 在写入本地文件时没有问题,但在下载文件时没有问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-31
    • 1970-01-01
    • 1970-01-01
    • 2012-03-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多