2013-03-26 4 views
1

J'ai une application écrite en C# (.Net 3.5) avec ce code.F # FTP échoue où C# réussit

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

J'ai traduit cela en F # (.Net 4.0) à utiliser dans ma demande.

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 
... 

A ce stade, FSI se plaint.

System.Net.WebException: The remote server returned an error: (550) File unavailable (e.g. file not found, no access).

Pourtant l'application C# s'exécute et télécharge avec succès le fichier. Que manque-t-il dans F # (à part les propriétés qui ne sont pas présentes dans 4.0, c'est-à-dire KeepAlive, UsePassive, et UseBinary)?

+3

Pourquoi croyez-vous que les propriétés supplémentaires de 'FtpWebRequest' sont manquants? Ils sont [là] (http://msdn.microsoft.com/en-us/library/system.net.ftpwebrequest_properties%28v=vs.100%29.aspx): 'ftp.KeepAlive <- true; ftp.UsePassive <- false; ftp.UseBinary <- false' –

+0

OK. Je jure, j'ai vérifié IntelliSense trois fois en l'espace de deux heures, et ces propriétés ne sont jamais apparues. Maintenant, ils le font. MAIS: ils ne font pas de différence. J'ai la même erreur. –

+2

Ensuite, il est logique de regarder [ce SO] (http://stackoverflow.com/questions/6251169/ftpwebrequest-net-3-5-vs-4) que vous utilisez le mode FTP actif. Je vérifierais très rapidement que votre C# est OK sous .net 4.0 avant de suspecter F # de quelque chose de mal. –

Répondre

5

Le code peut avoir des erreurs, je n'ai pas de compilateur F # en ce moment.

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 

Source: http://support.microsoft.com/kb/2134299

The cause of this issue is due to a behavior change in the System.Net.FtpWebRequest class in .Net Framework 4. There has been a change made to the System.Net.FtpWebRequest class from .Net Framework 3.5 to .Net Framework 4 to streamline the use of the CWD protocol commands. The new implementation of the System.Net.FtpWebRequest class prevents the send of extra CWD commands before issuing the actual command which the user requested and instead directly sends the requested command. For fully RFC compliant FTP servers, this should not be an issue, however for non-fully RFC compliant servers, you will see these types of errors.

+0

Wow! Merci beaucoup! –

0

Essayez ceci:

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;; 

je dû ajouter un parm1 factice et param2 mais je suppose que vous avez parm1 et param2 défini dans votre code actuel. Je suppose que quel que soit le problème, il réside dans la chaîne de l'uri. C'est-à-dire, je pense que vous trouverez le problème en comparant l'uri à la chaîne connue de l'uri.

+0

J'ai effectivement comparé les chaînes uri de F # et C#, et elles sont identiques, je publierais les chaînes de caractères uri, mais je pense que mon entreprise obtiendrait C'est pourquoi j'ai laissé les paramètres non définis, et leurs vrais noms ont changé.Pour mon code, leurs valeurs sont définies via un fichier de configuration –

+0

J'ai également essayé System.String.Format() comme vous l'avez suggéré, résultant dans le même (correct) uri, et la même erreur. –

Questions connexes