1

我有一个使用此代码用 C# (.Net 3.5) 编写的应用程序。

using System;
using System.Net;

string strURI = String.Format("ftp://x{0}ftp/%2F'{1}'", parm1, parm2);
FtpWebRequest ftp = (FtpWebRequest)FtpWebRequest.Create(strURI);
ftp.Proxy = null;
ftp.KeepAlive = true;
ftp.UsePassive = false;
ftp.UseBinary = false;
ftp.Credentials = new NetworkCredential("uid", "pass");
ftp.Method = WebRequestMethods.Ftp.DownloadFile;
FtpWebResponse response = (FtpWebResponse)ftp.GetResponse();
...

我已将其翻译成 F# (.Net 4.0) 以在我的应用程序中使用。

open System.Net

let uri = sprintf "ftp://x%sftp/%%2F'%s'" parm1 parm2
let ftp = FtpWebRequest.Create(uri) :?> FtpWebRequest
ftp.Credentials <- new NetworkCredential("uid", "pass")
ftp.Method <- WebRequestMethods.Ftp.DownloadFile
ftp.Proxy <- null
let response = ftp.GetResponse() :?> FtpWebResponse
...

在这一点上,FSI 抱怨。

System.Net.WebException:远程服务器返回错误:(550)文件不可用(例如,找不到文件,无法访问)。

然而,C# 应用程序运行并成功下载了该文件。我在 F# 中缺少什么(除了 4.0 中没有的属性,即 KeepAlive、UsePassive 和 UseBinary)?

4

2 回答 2

5

代码可能有错误,我现在没有 F# 编译器。

open System
open System.Reflection
open System.Net

let switch_to_legacy_mode _ =
  let wtype = typeof<FtpWebRequest>
  let mfield = wtype.GetField("m_MethodInfo", BindingFlags.NonPublic ||| BindingFlags.Instance)
  let mtype = mfield.FieldType
  let knfield = mtype.GetField("KnownMethodInfo", BindingFlags.Static ||| BindingFlags.NonPublic)
  let knarr = knfield.GetValue(null) :?> Array
  let flags = mtype.GetField("Flags", BindingFlags.NonPublic ||| BindingFlags.Instance)
  let flag_val = 0x100
  for f in knarr do
    let mutable ff = flags.GetValue(f) :?> int
    ff <- ff ||| flag_val
    flags.SetValue(f, ff)

let uri = sprintf "ftp://x%sftp/%%2F'%s'" parm1 parm2
do switch_to_legacy_mode () // Call it once before making first FTP request
let ftp = FtpWebRequest.Create(uri) :?> FtpWebRequest
ftp.Credentials <- new NetworkCredential("uid", "pass")
ftp.Method <- WebRequestMethods.Ftp.DownloadFile
ftp.Proxy <- null
let response = ftp.GetResponse() :?> FtpWebResponse

来源: http: //support.microsoft.com/kb/2134299

此问题的原因是由于 .Net Framework 4 中 System.Net.FtpWebRequest 类的行为更改。 System.Net.FtpWebRequest 类已从 .Net Framework 3.5 更改为 .Net Framework 4 到简化 CWD 协议命令的使用。System.Net.FtpWebRequest 类的新实现防止在发出用户请求的实际命令之前发送额外的 CWD 命令,而是直接发送请求的命令。对于完全符合 RFC 的 FTP 服务器,这应该不是问题,但是对于不完全符合 RFC 的服务器,您会看到这些类型的错误。

于 2013-03-27T18:46:55.497 回答
0

试试这个:

open System
open System.Net

let parm1 = "test"
let parm2 = "othertest"

let uri = String.Format("ftp://x{0}ftp/%2F'{1}'", parm1, parm2)
let ftp = FtpWebRequest.Create(uri) :?> FtpWebRequest;;

我必须添加一个虚拟的 parm1 和 parm2,但我假设您已经在实际代码中定义了 parm1 和 parm2。我猜想无论问题是什么,它都存在于 uri 字符串中。也就是说,我认为您可以通过将 uri 与已知良好的 uri 字符串进行比较来发现问题。

于 2013-03-27T01:09:14.500 回答