WCF REST用jquery下载pdf

Posted

技术标签:

【中文标题】WCF REST用jquery下载pdf【英文标题】:WCF REST Downloading pdf with jquery 【发布时间】:2017-08-14 06:11:18 【问题描述】:

我正在尝试使用 jquery ajax 调用从 WCF REST 服务下载 pdf 文件,但我认为存在编码问题。

这是服务接口方法定义

[OperationContract]
    [WebInvoke(
        BodyStyle = WebMessageBodyStyle.Bare,
       ResponseFormat = WebMessageFormat.Json,
       RequestFormat = WebMessageFormat.Json, 
        Method="POST", 
        UriTemplate = "DownloadFile")]
    Stream DownloadFile(RequestDownloadFile fileDownload);

然后是实现

 public Stream DownloadFile(RequestDownloadFile fileDownload)
 
       DBCepPortaleEntities cepPortale = CEP.DAL.DbConnections.GetConnessionePortale(ConnString); //connection with entity framework to SQLServer DB

        var cerco = from cc in cepPortale.WEB_DOCUMENTI
                    where cc.IdDocumento == fileDownload.ID
                    select cc; //retrieving a Pdf VARBINARY Field
        if (cerco.Count() > 0)
        



            WEB_DOCUMENTI doc = cerco.First();


            String nomeFile = @"test.pdf";
            String tmp = Encoding.Default.GetString(doc.DocPDF);
            File.WriteAllText(nomeFile, tmp, Encoding.Default);//test: pdf file is written correctly and I can read it
            WebOperationContext.Current.OutgoingResponse.ContentType = "application/pdf";
            WebOperationContext.Current.OutgoingResponse.Headers.Add("Content-disposition", "inline; filename=circolare" + fileDownload.ID + ".pdf");
            WebOperationContext.Current.OutgoingResponse.Headers.Add("Content-Transfer-Encoding", "binary");
            WebOperationContext.Current.OutgoingResponse.Headers.Add("Content-Encoding", "none");

            FileStream f = new FileStream(nomeFile, FileMode.Open);
            int length = (int)f.Length;
            WebOperationContext.Current.OutgoingResponse.ContentLength = length;
            byte[] buffer = new byte[length];
            int sum = 0;
            int count;
            while ((count = f.Read(buffer, sum, length - sum)) > 0)
            
                sum += count;
            
            f.Close();
            return new MemoryStream(buffer); 
       
        else
            return null;
 

此方法正确写入名为“test.pdf”的pdf文件。

现在我正在尝试通过 ajax 调用来使用它:

$.ajax(
                    method: "POST",
                    url: "http://testwcfcircolari.bresciapaghe.it/Service.svc/DownloadFile",
                    data: '"Token":"abc", "ID":"20"',
                    contentType: "application/json",
                    success: function (response, status, xhr) 
                        console.log(response);
                        //self.settings.onSuccessStart(response, status, xhr, self);

                        // Check if a filename is existing on the response headers.
                        var filename = "";
                        var disposition = xhr.getResponseHeader("Content-Disposition");
                        if (disposition && disposition.indexOf("attachment") !== -1) 
                            var filenameRegex = /filename[^;=\n]*=(([""]).*?\2|[^;\n]*)/;
                            var matches = filenameRegex.exec(disposition);
                            if (matches != null && matches[1])
                                filename = matches[1].replace(/[""]/g, "");
                        

                        filename = "prova.pdf";


                        var type = xhr.getResponseHeader("Content-Type");
                        var blob = new Blob([response],  type: "application/pdf; charset=UTF-8" );

                        if (typeof window.navigator.msSaveBlob !== "undefined") 
                            // IE workaround for "html7007: One or more blob URLs were revoked by closing the blob for which they were created. These URLs will no longer resolve as the data backing the URL has been freed.
                            window.navigator.msSaveBlob(blob, filename);
                         else 
                            var URL = window.URL || window.webkitURL;
                            var downloadUrl = URL.createObjectURL(blob);
                            alert(filename);
                            if (filename) 
                                // Use HTML5 a[download] attribute to specify filename.
                                var a = document.createElement("a");
                                // Safari doesn"t support this yet.
                                if (typeof a.download === "undefined") 
                                    window.location = downloadUrl;
                                 else 
                                    a.href = downloadUrl;
                                    a.download = filename;
                                    document.body.appendChild(a);
                                    a.click();
                                
                             else 
                                window.location = downloadUrl;
                            
                            //console.log(downloadUrl);
                            setTimeout(function () 
                                URL.revokeObjectURL(downloadUrl);
                            , 100); // Cleanup
                        
                        // Final custom event.
                        //self.settings.onSuccessFinish(response, status, xhr, self, filename);
                    ,
                    error: function (XMLHttpRequest, textStatus, errorThrown) 
                        alert('Error occurred while opening fax template' + XMLHttpRequest + " " +
                              +textStatus + " " + errorThrown);
                    
                );

结果是一个pdf文件,与原件有相同的页面,但内容都是空白的。 用文本编辑器观看下载的 pdf 的内容,与 starter 文件不同。

有什么建议吗? 谢谢。

【问题讨论】:

【参考方案1】:

C#

String[] filename=filepath.Split('\\');            
WebOperationContext.Current.OutgoingResponse.ContentType = "application/octet-stream";
if(File.Exists(filepath)

    String header = "attachment; filename=" + filename[filename.Length - 1];
    WebOperationContext.Current.OutgoingResponse.Headers["Content-Disposition"] = header;
    return File.OpenRead(filepath);

JS

function downloadfile(filepath)
     
 var url="https://myfile.ololo?v="+filepath;
 window.open(url,"windowname","width:400,height:300");
 

绑定

<bindings>
  <webHttpBinding>
    <binding name="MyWcfRestService.WebHttp" maxBufferSize="2147483637"
             maxBufferPoolSize="2147483637"
             maxReceivedMessageSize="2147483637"
             transferMode="Streamed"
             sendTimeout="00:05:00">
      <readerQuotas  maxDepth="2147483637"
                     maxStringContentLength="2147483637"
                     maxArrayLength="2147483647"
                     maxBytesPerRead="2147483647"
                     maxNameTableCharCount="2147483637"/>
      <security mode="None" />
    </binding>
  </webHttpBinding>
</bindings>

【讨论】:

非常感谢!这样,我将使用 GET 方法来检索文件,但我需要传递令牌以确保客户端获得访问确定文件的权限:在 GET 上传递令牌不安全。有办法吗?

以上是关于WCF REST用jquery下载pdf的主要内容,如果未能解决你的问题,请参考以下文章

Nodejs:如何从 REST API 下载 pdf 文件?

如何在rest wcf服务中上传pdf文件和其他字符串参数

JSON 中基于 WCF REST 的响应的 JQUERY AJAX

Jquery 无法从 WCF REST 服务获得响应

Jquery Rest 与 WCF 3.5 的通信

从 jquery 调用 wcf rest 服务不起作用