FtpWebRequest - 传输包含片段标记 (#) 的文件名

FtpWebRequest - Transferring file name containing fragment marker (#)

编辑:不确定它的答案,但它是一种解决方法......而不是查看我添加的文件传输对象。替换为 FTP 字符串并得到我正在寻找的结果,目标文件名现在与源文件名匹配。

FtpWebRequest ftpRequest = (FtpWebRequest)WebRequest.Create("ftp://" + targetServer + targetPath + fileInfo.Name.Replace("#", "%23"));


我有一个已使用多年的现有 C# FTP 进程。实施了一个新的文件命名约定,在实际文件名中使用# 字符。据我所知,# 在文件传输期间被解释为片段标记,导致目标服务器上的文件名不正确。

源文件名:'9300T_#Test.xml' 目标文件名:'9300T_'

有没有办法强制使用实际文件名?

当我在执行过程中查看对象值时,我可以看到原始字符串是正确的,但我还在片段 属性 下看到了“#Test.xml”。

我尝试了 WebRequest、FtpWebRequest 和 Uri 的不同属性。到目前为止,我还没有找到有效的组合,也没有在网上找到解决方案。

我已经使用其他 FTP 客户端(DOS 提示符、Mozilla)进行了测试,文件传输正确,这让我相信解决方案是由 属性 驱动的,或者,这是一个限制我正在使用的对象。

下面是我从产生问题的 windows 表单测试的代码。

谢谢。

        string sourcePath = @"C:\FILES\";
        string sourcePattern = "9300T*.xml";
        string targetServer = "test_server_name";
        string targetPath = "/";
        string targetLogin = "server_login";
        string targetPassword = "login_password";

        string[] uploadFiles = Directory.GetFiles(sourcePath, sourcePattern);

        // Loop through and process the list.
        foreach (string file in uploadFiles)
        {
            // Create the file information object.
            FileInfo fileInfo = new FileInfo(file);

            // Create the FTP request object.
            FtpWebRequest ftpRequest = (FtpWebRequest)WebRequest.Create("ftp://" + targetServer + targetPath + fileInfo.Name);
            ftpRequest.Credentials = new NetworkCredential(targetLogin, targetPassword);
            ftpRequest.KeepAlive = false;
            ftpRequest.Method = WebRequestMethods.Ftp.UploadFile;
            ftpRequest.UseBinary = true;
            ftpRequest.UsePassive = true;
            ftpRequest.ContentLength = fileInfo.Length; 

            // Opens a file stream to read the file being uploaded.
            FileStream readStream = fileInfo.OpenRead();

            // Create the stream to which the upload file is written to.
            Stream writeStream = ftpRequest.GetRequestStream();             // -- TARGET FILE IS CREATED WITH WRONG NAME AT THIS POINT

            // Set the buffer size.
            int bufferLength = 2048;
            byte[] buffer = new byte[bufferLength];

            // Read from and write to streams until content ends.
            int contentLength = readStream.Read(buffer, 0, bufferLength);
            while (contentLength != 0)
            {
                writeStream.Write(buffer, 0, contentLength);
                contentLength = readStream.Read(buffer, 0, bufferLength);
            }

            // Flush and close the streams.
            readStream.Flush();
            readStream.Close();

            writeStream.Flush();
            writeStream.Close();

            fileInfo.Delete();
        }

当您连接文件名以创建 URL 用于 Web 请求时, 您必须使用 percent-enconding, otherwise characters after "#" are considered to be URL fragment 而不是文件名的一部分来转义文件名。

我建议使用像 Uri.EscapeDataString() 这样的函数而不是 Replace("#", "%23"),因为它可以正确处理所有其他保留字符(例如“@”)。

FtpWebRequest ftpRequest = (FtpWebRequest)WebRequest.Create("ftp://" + targetServer + targetPath +  Uri.EscapeDataString(fileInfo.Name));

如果 targetPath 可能包含保留字符,您可能也需要对其进行转义。