C# 从URL-asp.net下载/流式传输文件
我需要流一个文件,这将导致在浏览器中的另存为提示。 问题是,文件所在的目录实际上已映射,因此我无法使用Server.MapPath确定其实际位置。该目录与网站不在同一位置(甚至不在live Box上的phyical服务器) 我希望类似于以下内容,但这将允许我传递一个web URL,而不是服务器文件路径 我可能不得不从配置基路径构建文件路径,然后附加到路径的其余部分,但希望我可以用这种方式来代替C# 从URL-asp.net下载/流式传输文件,c#,asp.net,file-io,streaming,C#,Asp.net,File Io,Streaming,我需要流一个文件,这将导致在浏览器中的另存为提示。 问题是,文件所在的目录实际上已映射,因此我无法使用Server.MapPath确定其实际位置。该目录与网站不在同一位置(甚至不在live Box上的phyical服务器) 我希望类似于以下内容,但这将允许我传递一个web URL,而不是服务器文件路径 我可能不得不从配置基路径构建文件路径,然后附加到路径的其余部分,但希望我可以用这种方式来代替 var filePath = Server.MapPath(DOCUMENT_PATH); if (
var filePath = Server.MapPath(DOCUMENT_PATH);
if (!File.Exists(filePath))
return;
var fileInfo = new System.IO.FileInfo(filePath);
Response.ContentType = "application/octet-stream";
Response.AddHeader("Content-Disposition", String.Format("attachment;filename=\"{0}\"", filePath));
Response.AddHeader("Content-Length", fileInfo.Length.ToString());
Response.WriteFile(filePath);
Response.End();
您可以尝试使用具有IIS路径前缀的DirectoryEntry类:
using(DirectoryEntry de = new DirectoryEntry("IIS://Localhost/w3svc/1/root" + DOCUMENT_PATH))
{
filePath = de.Properties["Path"].Value;
}
if (!File.Exists(filePath))
return;
var fileInfo = new System.IO.FileInfo(filePath);
Response.ContentType = "application/octet-stream";
Response.AddHeader("Content-Disposition", String.Format("attachment;filename=\"{0}\"", filePath));
Response.AddHeader("Content-Length", fileInfo.Length.ToString());
Response.WriteFile(filePath);
Response.End();
您可以使用HttpWebRequest获取文件并将其流式传输回客户端。这允许您使用url获取文件。我发现的一个例子是(但记不起在哪里给信用)
2年后,我使用了达拉斯的答案,但我不得不将
HttpWebRequest
更改为FileWebRequest
,因为我链接到了直接文件。不确定是否所有地方都是这样,但我想我应该加上它。而且,我删除了
var resp=Http.Current.Resonse
只要在引用
resp
的地方使用Http.Current.Response
。我经常这样做,我想我可以添加一个更简单的答案。我在这里设置了一个简单的课程,但是我每天晚上都运行这个课程来收集我关注的公司的财务数据
class WebPage
{
public static string Get(string uri)
{
string results = "N/A";
try
{
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(uri);
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
StreamReader sr = new StreamReader(resp.GetResponseStream());
results = sr.ReadToEnd();
sr.Close();
}
catch (Exception ex)
{
results = ex.Message;
}
return results;
}
}
在本例中,我传入一个url,它以HTML的形式返回页面。如果你想对流做一些不同的事情,你可以很容易地改变它
您可以这样使用它:
string page = WebPage.Get("http://finance.yahoo.com/q?s=yhoo");
将url下载到字节并将字节转换为流:
using (var client = new WebClient())
{
var content = client.DownloadData(url);
using (var stream = new MemoryStream(content))
{
...
}
}
如果我们在Citrix Netscaler上使用负载平衡器(没有WAF策略),达拉斯认可的解决方案对我们有效 当文件与WAF关联时,文件的下载无法通过Netscaler的LB工作,因为当前场景(内容长度不正确)是RFC冲突,并且AppFW重置连接,而当WAF策略未关联时,不会发生这种情况 因此,缺少的是: 响应。结束()强> 另见:
如果您正在寻找@Dallas答案的.NET核心版本,请使用以下选项
Stream stream = null;
//This controls how many bytes to read at a time and send to the client
int bytesToRead = 10000;
// Buffer to read bytes in chunk size specified above
byte[] buffer = new Byte[bytesToRead];
// The number of bytes read
try
{
//Create a WebRequest to get the file
HttpWebRequest fileReq = (HttpWebRequest)HttpWebRequest.Create(@"file url");
//Create a response for this request
HttpWebResponse fileResp = (HttpWebResponse)fileReq.GetResponse();
if (fileReq.ContentLength > 0)
fileResp.ContentLength = fileReq.ContentLength;
//Get the Stream returned from the response
stream = fileResp.GetResponseStream();
// prepare the response to the client. resp is the client Response
var resp = HttpContext.Response;
//Indicate the type of data being sent
resp.ContentType = "application/octet-stream";
//Name the file
resp.Headers.Add("Content-Disposition", "attachment; filename=test.zip");
resp.Headers.Add("Content-Length", fileResp.ContentLength.ToString());
int length;
do
{
// Verify that the client is connected.
if (!HttpContext.RequestAborted.IsCancellationRequested)
{
// Read data into the buffer.
length = stream.Read(buffer, 0, bytesToRead);
// and write it out to the response's output stream
resp.Body.Write(buffer, 0, length);
//Clear the buffer
buffer = new Byte[bytesToRead];
}
else
{
// cancel the download if client has disconnected
length = -1;
}
} while (length > 0); //Repeat until no data is read
}
finally
{
if (stream != null)
{
//Close the input stream
stream.Close();
}
}
你能详细说明一下“虚拟映射”的含义吗?可通过URL访问的虚拟IIS文件夹?它使用VPP路径,这是EpiServer CMS使用的概念。我们设置虚拟路径名(即“/documents/”),然后指定该路径也应映射的物理路径(即“//servername/documents”)。然后,系统在运行时创建对目录的引用。您可以通过web URL浏览到文件,而无需发出任何问题。文件名确实可以通过URL访问。我需要使用此URL来流式传输文件,而不是服务器路径,因为我无法从URL(使用MapPath)中删除此URL。如果您知道URL,并且文件扩展名在浏览器中打开“另存为”提示(或者这是您的问题之一),也许您可以将请求重定向到要下载的文件?否则,user97970的建议似乎是可行的。每次运行时刷新响应和重新创建缓冲区都是不必要的——这只会减慢传输速度。另外,我认为应该重命名一些变量(fileReq->urlRequest,fileResp->urlResponse)。另外,没有理由创建Stream变量,在开始时,您应该在使用它的地方创建它(靠近GetResponseStream()调用)@data\u smith为什么不试试您的建议呢?它不会编译。缓冲区的作用是降低web服务器上的内存使用率。本例中未定义resp:代码未编译。正如@Sharon所述,此代码未编译。您需要做的是,在注释处读取
//准备对客户端的响应。resp是客户端响应,添加此代码位:var resp=HttpContext.Current.Response代码>@Dallas谢谢你的样品,它让我很开心。我在构建一个服务时使用它,该服务将mp3文件流式传输到Windows Phone 7客户端,其中AudioPlayerAgent无法处理重定向302,然后需要直接返回文件流。我的情况不同,有一个文档管理系统,以.tif格式返回文档,其中在querystring中发送no。但这种方法行不通,任何想法都值得赞赏。thanks@kayhanyüksel:我尝试了那个链接,但它超时了。对不起,太好了。我把达拉的答案删掉了一点。我在下面发布了我的版本,虽然这看起来很简单,工作也很好,但是你需要记住,这个解决方案会将文件加载到你的计算机内存中。因此,当1)一个数据太大或2)同时发出多个请求时,由于内存不足而导致异常的可能性很高。Benjamin,这个问题可以通过使用来缓解。
Stream stream = null;
//This controls how many bytes to read at a time and send to the client
int bytesToRead = 10000;
// Buffer to read bytes in chunk size specified above
byte[] buffer = new Byte[bytesToRead];
// The number of bytes read
try
{
//Create a WebRequest to get the file
HttpWebRequest fileReq = (HttpWebRequest)HttpWebRequest.Create(@"file url");
//Create a response for this request
HttpWebResponse fileResp = (HttpWebResponse)fileReq.GetResponse();
if (fileReq.ContentLength > 0)
fileResp.ContentLength = fileReq.ContentLength;
//Get the Stream returned from the response
stream = fileResp.GetResponseStream();
// prepare the response to the client. resp is the client Response
var resp = HttpContext.Response;
//Indicate the type of data being sent
resp.ContentType = "application/octet-stream";
//Name the file
resp.Headers.Add("Content-Disposition", "attachment; filename=test.zip");
resp.Headers.Add("Content-Length", fileResp.ContentLength.ToString());
int length;
do
{
// Verify that the client is connected.
if (!HttpContext.RequestAborted.IsCancellationRequested)
{
// Read data into the buffer.
length = stream.Read(buffer, 0, bytesToRead);
// and write it out to the response's output stream
resp.Body.Write(buffer, 0, length);
//Clear the buffer
buffer = new Byte[bytesToRead];
}
else
{
// cancel the download if client has disconnected
length = -1;
}
} while (length > 0); //Repeat until no data is read
}
finally
{
if (stream != null)
{
//Close the input stream
stream.Close();
}
}