C# 使用FtpWebRequest下载文件时获取文件名而不是内容
我正在尝试编写一个工具,可以从人口普查局的TIGER FTP站点下载Shapefile,该站点位于:。我可以很好地列出文件,但是当我尝试下载文件时,我得到的字符串只是文件名,而不是文件内容本身。代码如下C# 使用FtpWebRequest下载文件时获取文件名而不是内容,c#,download,ftp,ftpwebrequest,C#,Download,Ftp,Ftpwebrequest,我正在尝试编写一个工具,可以从人口普查局的TIGER FTP站点下载Shapefile,该站点位于:。我可以很好地列出文件,但是当我尝试下载文件时,我得到的字符串只是文件名,而不是文件内容本身。代码如下 private static T FtpRequest<T, TReader>(string url, string method, Func<TReader, T> responseAction) where TReader : IDisposable {
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();
}
private static T FtpRequest(字符串url、字符串方法、函数响应),其中TReader:IDisposable{
var request=(FtpWebRequest)WebRequest.Create(url);
request.Method=WebRequestMethods.Ftp.ListDirectory;
request.Credentials=新的网络凭据(“匿名”、“匿名”);
request.UseBinary=true;
request.usesponsive=true;
var response=(FtpWebResponse)request.GetResponse();
使用(var responseStream=response.GetResponseStream())
使用(var reader=(TReader)Activator.CreateInstance(typeof(TReader),responseStream)){
返回响应(读卡器);
}
}
私有静态IList列表目录(字符串url){
返回FtpRequest(url,
WebRequestMethods.Ftp.ListDirectory,
(StreamReader)=>reader.ReadAllLines()
.Select(文件=>newURI(新Uri(url),新Uri(文件,UriKind.Relative)).AbsoluteUri)
.ToArray());
}
私有静态字节[]下载二进制文件(字符串url){
//注意:以下代码适用于4.6,但不适用于3.5
//使用(var client=new WebClient()){
//返回client.DownloadData(url);
//}
//此代码在4.6和3.5中都以字符串形式返回文件名
返回FtpRequest(url,
WebRequestMethods.Ftp.DownloadFile,
(二进制读取器)=>{
使用(var memoryStream=new memoryStream()){
var buffer=新字节[2048];
对于(;;){
var bytesRead=reader.Read(buffer,0,buffer.Length);
如果(字节读==0)
打破
memoryStream.Write(缓冲区,0,字节读取);
}
memoryStream.Position=0;
返回memoryStream.GetBuffer();
}
});
}
内部静态void Main(字符串[]args){
var baseUrl=”ftp://ftp2.census.gov/geo/tiger/TIGER2015/TRACT";
foreach(ListDirectory(baseUrl)中的var文件){
WriteLine(“下载:{0}”,文件);
var contents=下载二进制文件(file);
使用(var zipStream=新内存流(内容))
使用(var zipFile=zipFile.Read(zipStream)){
foreach(zipFile中的var条目){
WriteLine(“->{0}”,entry.FileName);
//使用(var entryReader=entry.OpenReader()){
//}
}
}
}
Console.ReadKey();
}
如果我使用WebClient
,它在.NET3.5中会失败并出现550错误,但在.NET4.6中可以正常工作。上面注释掉了相关代码
人口普查网站有点挑剔,所以他们的网站很可能做了一些奇怪的事情。这就是为什么我提供了URL,以防任何比我更了解FTP的人都能诊断出一个坏服务器。在您的
FtpRequest
方法中,您总是使用WebRequestMethods.FTP.ListDirectory
方法,即使用于下载。因此,您实际上“列出”了该文件,这就是为什么您在响应中得到它的名称
您必须使用下载文件。如果您为问题创建了,您自己就会发现问题。看看我的答案,我真傻。我是说,哇,这是一个重大疏忽。让我们把责任推到星期一吧。