C# 检测PHP链接导致文件在c中下载#
我似乎找不到一个有效的答案来解决我的问题,我想知道是否有人能帮上忙。基本上,我的网站上有一个链接,可以下载zip文件:C# 检测PHP链接导致文件在c中下载#,c#,php,file,download,detect,C#,Php,File,Download,Detect,我似乎找不到一个有效的答案来解决我的问题,我想知道是否有人能帮上忙。基本上,我的网站上有一个链接,可以下载zip文件: http://***.com/download.php?id=1 如果您在网页上激活此链接,它将弹出另存为对话框,并允许您使用默认名称保存文件ThisIsMyZipFile.zip 我的问题是,在c#下,如果我使用newURI(“http://***.com/download.pgp?id=1”).IsFile它返回false,因此如果不执行webclient Downloa
http://***.com/download.php?id=1
如果您在网页上激活此链接,它将弹出另存为对话框,并允许您使用默认名称保存文件ThisIsMyZipFile.zip
我的问题是,在c#下,如果我使用newURI(“http://***.com/download.pgp?id=1”).IsFile
它返回false
,因此如果不执行webclient DownloadString
并查看前两个字节是否为PK
,我似乎无法检测到这是一个文件
此外,即使手动下载为字符串,检测PK
标题并保存文件,我也无法找到我的网站想要使用的默认文件名是ThisIsMyZipFile.zip,因为我想使用相同的文件名
有人知道解决这两个问题的好方法吗
更新
多亏了Paul和他的回答,我创建了以下函数,它正好满足了我的需要:
/// <summary>
/// Returns the responded HTTP headers of the given URL and if the link refers to the file it returns extra information about it.
/// </summary>
/// <param name="Url">The address.</param>
/// <returns>
/// null if a WebException is thrown
/// otherwise:
/// List of headers:
/// Keep-Alive - Timeout value (i.e. timeout=2, max=100)
/// Connection - The type of connection (i.e. Keep-Alive)
/// Transfer-Encoding - The type of encoding used for the transfer (i.e. chunked)
/// Content-Type - The type of Content that will be transferred (i.e. application/zip)
/// Date - The servers date and time
/// Server - The server that is handling the request (i.e. Apache)
/// AbsoluteUri - The full Uri of the resulting link that will be followed.
/// The following key will be present if the link refers to a file
/// Filename - The filename (not path) of the file that will be downloaded if the link if followed.
/// </returns>
public Dictionary<string, string> GetHTTPResponseHeaders(string Url)
{
WebRequest WebRequestObject = HttpWebRequest.Create(Url);
WebResponse ResponseObject = null;
try
{
ResponseObject = WebRequestObject.GetResponse();
}
catch(WebException ex)
{
return null;
}
// Add the header inforamtion to the resulting list
Dictionary<string, string> HeaderList = new Dictionary<string, string>();
foreach (string HeaderKey in ResponseObject.Headers)
HeaderList.Add(HeaderKey, ResponseObject.Headers[HeaderKey]);
// Add the resolved Uri to the resulting list
HeaderList.Add("AbsoluteUri", ResponseObject.ResponseUri.AbsoluteUri);
// If this is a zip file then add the download filename specified by the server to the resulting list
if (ResponseObject.ContentType.ToLower() == "application/zip")
{
HeaderList.Add("Filename", ResponseObject.ResponseUri.Segments[ResponseObject.ResponseUri.Segments.Length-1]);
}
// We are now finished with our response object
ResponseObject.Close();
// Return the resulting list
return HeaderList;
}
//
///返回给定URL的响应HTTP头,如果链接引用该文件,则返回有关该文件的额外信息。
///
///地址。
///
///如果引发WebException,则为null
///否则:
///标题列表:
///保持活动-超时值(即超时=2,最大=100)
///连接-连接类型(即保持活动)
///传输编码-用于传输的编码类型(即分块)
///内容类型-将传输的内容类型(即应用程序/zip)
///日期-服务器的日期和时间
///服务器-处理请求的服务器(即Apache)
///AbsoluteUri—将遵循的结果链接的完整Uri。
///如果链接引用文件,则会出现以下键
///Filename-如果遵循链接,将下载的文件的文件名(而不是路径)。
///
公共字典GetHTTPResponseHeaders(字符串Url)
{
WebRequestWebRequestObject=HttpWebRequest.Create(Url);
WebResponse ResponseObject=null;
尝试
{
ResponseObject=WebRequestObject.GetResponse();
}
捕获(WebException ex)
{
返回null;
}
//将标题信息添加到结果列表中
字典标题列表=新字典();
foreach(ResponseObject.Headers中的字符串HeaderKey)
添加(HeaderKey,ResponseObject.Headers[HeaderKey]);
//将解析的Uri添加到结果列表中
添加(“AbsoluteUri”,ResponseObject.ResponseUri.AbsoluteUri);
//如果这是zip文件,则将服务器指定的下载文件名添加到结果列表中
if(ResponseObject.ContentType.ToLower()=“应用程序/zip”)
{
添加(“文件名”,ResponseObject.ResponseUri.Segments[ResponseObject.ResponseUri.Segments.Length-1]);
}
//现在,我们已经完成了响应对象
ResponseObject.Close();
//返回结果列表
返回标题列表;
}
Uri.IsFile
对Uri执行静态检查,即查看“scheme”部分(包括冒号的第一位)是否为文件:
。它不会查看通过请求驻留在URI上的资源而返回的实际内容。(事实上,因为它实际上根本没有尝试联系服务器,所以URI实际上可能指向丢失的资源,而IsFile
仍然可以工作。)
如果希望查看资源的内容是否属于特定类型,则必须:
检索资源的HTTP头(如果是HTTP或HTTPs资源:即,如果“方案”是HTTP
或HTTPs
)
检索(至少部分)资源并检查它
您当前正在执行2,但是对于HTTP资源(具有HTTP URL),执行1会更干净、更便宜。您可以通过执行HTTPHEAD
请求来实现这一点(与GET
或POST
,&c相反)。这将返回HTTP头,而不返回资源本身。代码将类似于:
var request = WebRequest.Create("http://somewhere.overtherainbow.com/?a=b");
request.Method = "HEAD";
WebResponse response = request.GetResponse();
//TODO check status code
string contentType = response.ContentType;
response.Close();
内容类型将为您提供一些文件类型的指示,但是许多二进制文件将作为八位字节流返回,因此如果您希望区分不同的二进制文件类型,您可能仍然需要检索和检查资源本身的魔法字节。(不过,内容类型应该足以让您区分二进制文件和网页。)
因此,完整的解决方案可能是:
发送资源的GET
请求
检查响应状态以确保没有错误
检查content-type头以查看是否有二进制八位字节流
从响应流中读取两个字节,查看文件是否启动“PK”
如果不向该URL发送HTTP请求,则绝对无法检测到给定URL会导致下载文件
现在来看第二个问题。您可以发送HTTP请求以下载该文件,然后检查将包含文件名的内容处置标头:
using (var client = new WebClient())
{
using (var stream = client.OpenRead("http://*.com/download.php?id=1"))
{
var disposition = client.ResponseHeaders["Content-Disposition"];
if (disposition != null)
{
var cd = new ContentDisposition(disposition);
if (!cd.Inline && !string.IsNullOrEmpty(cd.FileName))
{
using (var outputStream = File.OpenWrite(cd.FileName))
{
stream.CopyTo(outputStream);
}
}
}
else
{
// The web server didn't send a Content-Disposition response header
// so we have absolutely no means of determining the filename
// you will have to use some default value here if you want to store it
}
}
}
MSDN说,只有当IsFile与URI模式文件匹配时,它才是真的。瞧,谢谢保罗,这正是我所需要的。:-)