检测PHP链接是否会导致c#中的文件下载
本文关键字:文件下载 PHP 链接 是否 检测 | 更新日期: 2023-09-27 17:49:42
我似乎找不到一个有效的答案来解决我的问题,我想知道是否有人可以帮助我。基本上,我的网站上有一个链接,可以下载一个zip文件:
http://***.com/download.php?id=1
如果你在网页上激活这个链接,它会弹出一个另存为对话框,让你用默认名称ThisIsMyZipFile.zip
保存文件
我的问题是,在c#下,如果我使用new Uri("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;
}
Uri.IsFile
对URI执行静态检查,即它查看'scheme'部分(包括冒号的第一个位)是否为file:
。它不查看通过请求驻留在URI中的资源返回的实际内容。(事实上,因为它实际上根本没有尝试联系服务器,所以URI实际上可能指向丢失的资源,而IsFile
仍然可以工作。)
如果您希望查看资源的内容是否属于特定类型,那么您必须:
- 检索资源的HTTP报头(如果它是HTTP或HTTPs资源:也就是说,如果'方案'是
http
或https
)。 - 检索(至少部分)资源并检查它。
您目前正在执行2,但对于HTTP资源(带有HTTP URL),那么执行1将更干净,更便宜。您可以通过执行HTTP HEAD
请求(与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
请求 - 检查响应状态以确保没有错误。
- 检查内容类型头,看看我们是否有二进制八字节流。
- 从响应流中读取两个字节,看看文件是否开始"PK"。
如果不向该URL发送HTTP请求,您绝对无法检测到给定的URL会导致文件被下载。
现在讨论第二个问题。你可以发送一个HTTP请求来下载文件,然后检查Content-Disposition头,它将包含文件名:
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
}
}
}