Asp.net mvc .Net Web API PDF下载不起作用

Asp.net mvc .Net Web API PDF下载不起作用,asp.net-mvc,pdf,asp.net-web-api,download,durandal,Asp.net Mvc,Pdf,Asp.net Web Api,Download,Durandal,我正在开发一个基于.NETMVC5项目的Durandal应用程序。我有一个WebAPI2控制器,它通过获取一些数据并使用将其合并到现有的PDF模板中来生成PDF。这很好,我可以将新的PDF保存到磁盘我的问题是,我想将新的PDF流式传输到浏览器,以便用户可以下载它-但它不起作用。我尝试了许多解决方案,但都没有效果 理想情况下,我甚至不希望将生成的PDF保存到磁盘,因为它似乎没有必要。这是我尝试的第一种方法——将所有内容都保存在内存中,将新的PDF写入字节数组并将其发送回浏览器。在尝试了所有我能找到

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

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

下面是api请求之后的响应头 但在浏览器(最新版本的Chrome、Firefox和IE)中什么也没有发生。 以下是我的控制器和下载方法: 我在客户端使用Durandal/Knockout/Breeze,在服务器端使用EF6、Breeze和webapi2。我已确保包含PDF的文件夹具有完整的安全权限,并将
runAllManagedModulesForAllRequests=“true”
属性放在我的web.config中的
modules
元素上


有什么想法吗?

你应该可以用字节数组来实现这一点,没问题。我觉得你的服务器代码很好

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


当用户单击链接时,它将执行GET,结果响应将触发文件下载对话框。如果您将媒体类型设置为
application/pdf
,那么像Chrome这样的浏览器将直接呈现它。

下面就是一个例子
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
[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;

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