我正在尝试编写一种可以从人口普查局的TIGER FTP站点下载shapefile的工具,该站点位于:ftp : //ftp2.census.gov/geo/tiger/TIGER2015/TRACT。我能够很好地列出文件,但是当我尝试下载文件时,我得到的字符串只是文件名,而不是文件内容本身。代码如下。
private static T FtpRequest<T, TReader>(string url, string method, Func<TReader, T> responseAction) where TReader : IDisposable {
var request = (FtpWebRequest)WebRequest.Create(url);
request.Method = WebRequestMethods.Ftp.ListDirectory;
request.Credentials = new NetworkCredential("anonymous", "anonymous");
request.UseBinary = true;
request.UsePassive = true;
var response = (FtpWebResponse)request.GetResponse();
using(var responseStream = response.GetResponseStream())
using(var reader = (TReader)Activator.CreateInstance(typeof(TReader), responseStream)) {
return responseAction(reader);
}
}
private static IList<string> ListDirectory(string url) {
return FtpRequest(url,
WebRequestMethods.Ftp.ListDirectory,
(StreamReader reader) => reader.ReadAllLines()
.Select(file => new Uri(new Uri(url), new Uri(file, UriKind.Relative)).AbsoluteUri)
.ToArray());
}
private static byte[] DownloadBinaryFile(string url) {
// NOTE: following code works in 4.6, but not 3.5
//using(var client = new WebClient()) {
// return client.DownloadData(url);
//}
// this code returns file name as string in both 4.6 and 3.5
return FtpRequest(url,
WebRequestMethods.Ftp.DownloadFile,
(BinaryReader reader) => {
using(var memoryStream = new MemoryStream()) {
var buffer = new byte[2048];
for(;;) {
var bytesRead = reader.Read(buffer, 0, buffer.Length);
if(bytesRead == 0)
break;
memoryStream.Write(buffer, 0, bytesRead);
}
memoryStream.Position = 0;
return memoryStream.GetBuffer();
}
});
}
internal static void Main(string[] args) {
var baseUrl = "ftp://ftp2.census.gov/geo/tiger/TIGER2015/TRACT";
foreach(var file in ListDirectory(baseUrl)) {
Console.WriteLine("Downloading: {0}", file);
var contents = DownloadBinaryFile(file);
using(var zipStream = new MemoryStream(contents))
using(var zipFile = ZipFile.Read(zipStream)) {
foreach(var entry in zipFile) {
Console.WriteLine(" -> {0}", entry.FileName);
//using(var entryReader = entry.OpenReader()) {
//}
}
}
}
Console.ReadKey();
}
如果使用WebClient
,.NET 3.5失败并显示550错误,但.NET 4.6正常工作。相关代码已在上面注释掉。
人口普查站点有点挑剔,因此他们的站点很可能在做奇怪的事情。这就是为什么我提供URL的原因,以防任何比我了解更多FTP知识的人都可以诊断出服务器故障。
在您FtpRequest
的WebRequestMethods.Ftp.ListDirectory
方法中,即使下载也要始终使用该方法。因此,您实际上是在“列出”文件,这就是为什么在响应中获得文件名的原因。
您必须使用该WebRequestMethods.Ftp.DownloadFile
方法下载文件。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句