F#FTP在C#成功的地方失败

时间:2013-03-26 18:43:20

标签: ftp f#

我使用此代码用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)?

2 个答案:

答案 0 :(得分: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类。有一个   从.Net Framework更改到System.Net.FtpWebRequest类   3.5到.Net Framework 4简化了CWD协议命令的使用。 System.Net.FtpWebRequest类的新实现   在发出实际命令之前阻止发送额外的CWD命令   用户请求的命令,而是直接发送   请求的命令。对于完全符合RFC的FTP服务器,这应该是   这不是一个问题,但对于非完全符合RFC的服务器,你会   看到这些类型的错误。

答案 1 :(得分: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字符串找到问题。