C# 如何从外部服务器初始化文件下载?
我有一个定义如下的MVC控制器方法:C# 如何从外部服务器初始化文件下载?,c#,javascript,asp.net-mvc-3,C#,Javascript,Asp.net Mvc 3,我有一个定义如下的MVC控制器方法: public ActionResult GetPdf(string filename) { var pdfDownload = File("~/Content/GeneratedReports/report1.pdf", "application/pdf", Server.UrlEncode("report1.pdf")); return pdfDownload; } 如果将
public ActionResult GetPdf(string filename)
{
var pdfDownload = File("~/Content/GeneratedReports/report1.pdf", "application/pdf", Server.UrlEncode("report1.pdf"));
return pdfDownload;
}
如果将第一个参数更改为托管在单独云服务器上的服务器的url,则会出现以下错误:
“我的文件路径”不是有效的虚拟路径
我只希望我的客户能够下载一个文件。这似乎比实际需要复杂得多
我有一个指向PDF的URL。我希望我的客户在不点击任何东西的情况下下载该pdf。(服务响应成功后,下载将启动)
为什么这么难,我该如何解决
我不在乎解决方案是JS还是MVC….您可以在远程报告中重定向用户;如果这不是一个选项,您将需要代理它:
byte[] blob;
using(var client = new WebClient()) {
blob = client.DownloadData(remoteUrl);
}
return File(blob, "application/pdf", "report1.pdf");
以上假设文件不是很大;一个更健壮的实现将获取和发送数据块
为什么这么难,我该如何解决
事实上,这并不难:
public ActionResult GetPdf(string filename)
{
using (var client = new WebClient())
{
var buffer = client.DownloadData("http://foo.com/bar.pdf");
return File(buffer, "application/pdf", "report1.pdf");
}
}
现在很明显,这个方法有一个严重的缺陷,因为它在内存中传输文件。虽然这对于小报告来说非常有效,但对于大文件来说可能会有问题,如果有很多用户迫不及待地想把他们的手放在这个伟大的报告上,那么问题就更大了 第一个控制器操作还存在另一个严重缺陷。它混合了责任。它包含基础架构代码,我要求您单独进行单元测试 因此,让我们通过编写自定义操作结果来解决这两个严重问题:
public class ReportResult : ActionResult
{
private readonly string _filename;
public ReportResult(string filename)
{
_filename = filename;
}
public override void ExecuteResult(ControllerContext context)
{
var cd = new ContentDisposition
{
FileName = _filename,
Inline = false
};
var response = context.HttpContext.Response;
response.ContentType = "application/pdf";
response.Headers["Content-Disposition"] = cd.ToString();
using (var client = new WebClient())
using (var stream = client.OpenRead("http://foo.com/" + _filename))
{
// in .NET 4.0 implementation this will process in chunks
// of 4KB
stream.CopyTo(response.OutputStream);
}
}
}
您将这样使用:
public ActionResult GetPdf(string filename)
{
return new ReportResult(filename);
}
在你看来:
@Html.ActionLink("Download report", "GetPdf", new { filename = "report.pdf" })
或者,您可以完全质疑控制器操作的有用性,因为在您看来,而不是:
@Html.ActionLink("Download report", "GetPdf")
你可以直接:
<a href="http://foo.com/bar.pdf">Download report</a>
当然,假设客户机可以访问此服务器
备注:在
Content Disposition
标题中发送的文件名要非常小心。我在你的问题中看到你使用了类似于Server.UrlEncode(“report1.pdf”)
的东西。我正在做一个类似的例行程序。现在我让它从本地驱动器访问图像
byte[]cimage=new WebClient().DownLoadData(System.Web.HttpContent.Server.MapPath(“~/Content/koala.jpg”)
如何访问SQL Server上的共享。我在SQL Server上的文件夹中有要检索的图像
byte[]cimage=new WebClient().DownLoadData(“Server share”+/Files/koala.jpg”);好的,
ActionResult
实现绝对值得投票(看一下数字),即使它会加速我自己的失败;p就我个人而言,我会使用一些参数,但它很好地显示了机制(编辑)该死,现在您也添加了参数;使用javascript,您可以简单地执行重定向:location.replace(externalUrlToDownload);
编写一个公开这些资源的web服务并从该服务下载文件。