.Net Web API PDF下载不起作用



我正在开发一个基于.Net MVC5项目的Durandal应用程序。我有一个Web API 2控制器,它通过获取一些数据并使用FDFToolkit将其合并到现有的PDF模板中来生成PDF。这很好用,我可以把新的PDF保存到磁盘上我的问题是,我想将新的PDF流式传输到浏览器,这样用户就可以下载它,但它不起作用我尝试了许多解决方案,但都无济于事。

理想情况下,我甚至不想把生成的PDF保存到磁盘上,因为这似乎没有必要。这是我尝试的第一种方法——将其全部保存在内存中,将新的PDF写入字节数组并发送回浏览器。在尝试了所有我能找到的解决方案后,我决定将新文件保存到磁盘上,并尝试将新文件流式传输到浏览器。我认为这将有助于缩小问题范围。

以下是我在api请求后的响应头

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 169729
Content-Type: application/octet-stream
Expires: -1
Server: Microsoft-IIS/8.0
Content-Disposition: attachment; filename=myEticket.pdf

但浏览器(Chrome、Firefox和IE的最新版本)中什么也没发生

这是我的控制器和下载方法:

[RoutePrefix("api/tickets")]
[AllowAnonymous] // for debugging only
public class EticketsController : ApiController
{
[HttpGet,HttpPost, Route("download")]
public HttpResponseMessage DownloadPdf([FromBody] Eticket model)
{
const string templateName = "eTicketFinal.pdf";
const string outputname = "eTicket_new.pdf";
var templatePdfPath = Path.Combine(HttpContext.Current.Server.MapPath("~/eTickets/"), templateName);
var outputpath = Path.Combine(HttpContext.Current.Server.MapPath("~/eTickets/"), outputname);
var eticket = _unitOfWork.EticketRepository.GetById(model.EticketId);
var pdfticket = Mapper.Map<EticketPdf>(eticket);
using (var fdfApp = new FDFApp_Class())
{
using (var fdfDoc = fdfApp.FDFCreate())
{
var properties = pdfticket.GetType().GetProperties();
foreach (var prop in properties)
{
var name = prop.Name;
var propvalue = prop.GetValue(pdfticket, null);
var value = propvalue == null ? string.Empty : propvalue.ToString();
fdfDoc.FDFSetValue(name, value);
}
// this is working and creating the file on disk
fdfDoc.PDFMergeFDF2File(outputpath, templatePdfPath);                  
fdfDoc.FDFClose();
}
}
var stream = new FileStream(outputpath, FileMode.Open);
var result = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StreamContent(stream)
};
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
//use attachment to force download
result.Content.Headers.ContentDisposition = new   ContentDispositionHeaderValue("attachment")
{
FileName = "myEticket.pdf"
};
return result;
}
}

发出api请求的Javascript:

$.ajax({
type: 'POST',
url: '/api/tickets/download',
data: postdata,
datatype: 'json',
contentType: 'application/json; charset=utf-8'
});

我在客户端使用Durandal/Knockout/Breeze,在服务器端使用EF6、Breeze和WebAPI2。我已经确保包含PDF的文件夹具有完全的安全权限,并将runAllManagedModulesForAllRequests="true"属性放在web.config中的modules元素上。

有什么想法吗?

使用字节数组应该可以做到这一点,没有问题。你的服务器代码对我来说很好。

我想问题是不能使用XHR/ajax类型的请求来触发浏览器中的文件下载工作流。您所需要做的就是在HTML中呈现一个<a>链接,其中href指向您的API端点。您还需要将服务器操作方法更改为GET。

当用户单击链接时,它将执行GET操作,得到的响应将触发"文件下载"对话框。如果您将媒体类型设置为application/pdf,则Chrome等浏览器将直接渲染它。

最新更新