摘要: 我正在使用 WebRequest 从我自己的互联网 DNS 中通过 FTP 下载 XML 文件。这是我第一次编写从 FTP 服务器下载文件的应用程序。我在下载中遇到了许多不一致的损坏,导致 XML 文件无法使用。下载文件的实际代码取自 Microsoft Windows 8 示例,名为:“Windows Store 应用程序中的 FTP 文件下载器”。我发现即使使用此 Windows 8 示例也会导致相同的损坏,因此它不一定是我的代码中的其他内容。
简介 My Windows Store App 使用 XML 文件存储数据。此数据最初来自 Excel。我需要每月更新这些数据,并使其无缝地提供给应用程序的用户。为此,我创建了一个网站,其中存储了最新版本的 XML 数据文件。这些文件是使用 Filezilla 以二进制传输模式上传的(顺便说一下,我发现 WebRequest 会从文件中删除所有的 CR/LF,如果它们是以 ASCII 格式上传的,使它们变得无用)。
我的应用程序将 Microsoft 示例中提供的代码用于 Windows 应用商店应用程序的 FTP 文件传输。它看起来像这样:
using System;
using System.IO;
using System.Net;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Windows.Storage;
using Windows.Storage.Streams;
namespace CSWindowsStoreAppFTPDownloader.FTP
{
public static class FTPClient
{
/// <summary>
/// Download a single file from FTP server using WebRequest.
/// </summary>
public static async Task<DownloadCompletedEventArgs>
DownloadFTPFileAsync(FTPFileSystem item,
StorageFile targetFile, ICredentials credential)
{
var result = new DownloadCompletedEventArgs
{
RequestFile = item.Url,
LocalFile = targetFile,
Error=null
};
// This request is FtpWebRequest in fact.
WebRequest request = WebRequest.Create(item.Url);
if (credential != null)
{
request.Credentials = credential;
}
request.Proxy = WebRequest.DefaultWebProxy;
// Set the method to Download File
request.Method = "RETR";
try
{
// Open the file for write.
using (IRandomAccessStream fileStream =
await targetFile.OpenAsync(FileAccessMode.ReadWrite))
{
// Get response.
using (WebResponse response = await request.GetResponseAsync())
{
// Get response stream.
using (Stream responseStream = response.GetResponseStream())
{
byte[] downloadBuffer = new byte[2048];
int bytesSize = 0;
// Download the file until the download is completed.
while (true)
{
// Read a buffer of data from the stream.
bytesSize = responseStream.Read(downloadBuffer, 0,
downloadBuffer.Length);
if (bytesSize == 0)
{
break;
}
// Write buffer to the file.
await fileStream.WriteAsync(downloadBuffer.AsBuffer());
}
}
}
}
}
catch (Exception ex)
{
result.Error=ex;
}
return result;
}
}
}
问题 XML 文件的格式应如下所示:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Table>
<Row>
<Month>JAN</Month>
<Year>1996</Year>
<RPI>74.6</RPI>
</Row>
<Row>
<Month>FEB</Month>
<Year>1996</Year>
<RPI>75.1</RPI>
</Row>
...
</Table>
但是,当我使用 MS 示例代码下载一个小的、格式正确的 XML 文件时,结束标记总是被损坏,如下所示:
<Row>
<Month>APR</Month>
<Year>2013</Year>
<RPI>114.92</RPI>
</Row>
</Table>/RPI>
</Row>
<Row>
<Month>APR</Month>
<Year>2011</Year>
<RPI>111.33</RPI>
</Row>
<Row>
<Month>MAY</
这段代码来自微软自己的网站,这让我有点担心。会不会是 FTP 服务器上的文件有问题?我使用 Filezilla 使用二进制传输模式下载这些文件没有问题。回顾以前的帖子,我可以看到二进制与 ASCII 是一个问题,但 WebRequest 没有 UseBinary 属性(与 Windows 8 中不可用的 FTPWebRequest 不同)。
我已经尝试了以下解决方法:
- 改变用于读取 WebResponse 并写入输出流的缓冲区大小 - 这具有移动损坏位置但不能消除它的效果
- 在每个读/写对之后将缓冲区重新初始化为新的 byte[] 数组 - 无效
- 将 byte[] 缓冲区的值设置为 0 - 这消除了结束标记的损坏,但 XML 中的其他间隙随机出现
我认为我不应该陷入这种显然不是最佳的解决方法的水平。有谁知道这里可能存在什么问题?谢谢你。