Javascript 动态PDF并打开新窗口而不是下载

Javascript 动态PDF并打开新窗口而不是下载,javascript,ajax,pdf,blob,Javascript,Ajax,Pdf,Blob,我有一个web api,它以编码字节数组的形式返回JSReport。无论我如何尝试读取字节数组,我都会收到一个黑屏或一条错误消息,上面写着“下载pdf失败”。如果我创建一个隐藏的锚定标记并下载pdf,它就可以正常工作。但是,我不希望用户下载它,我更希望他们可以直接从浏览器中查看它 WEB API调用 var data = LossReportService.GetLossSummary(request); var pdf_bytes = LossReportService.Gener

我有一个web api,它以编码字节数组的形式返回JSReport。无论我如何尝试读取字节数组,我都会收到一个黑屏或一条错误消息,上面写着“下载pdf失败”。如果我创建一个隐藏的锚定标记并下载pdf,它就可以正常工作。但是,我不希望用户下载它,我更希望他们可以直接从浏览器中查看它

WEB API调用

   var data = LossReportService.GetLossSummary(request);
   var pdf_bytes = LossReportService.GeneratePDFUsingJSReport(data);

   byte[] myBinary = new byte[pdf_bytes.Length];
   pdf_bytes.Read(myBinary, 0, (int)pdf_bytes.Length);
   string base64EncodedPDF = System.Convert.ToBase64String(myBinary);

   var response = Request.CreateResponse(HttpStatusCode.OK, base64EncodedPDF);
   response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
   response.Content.Headers.ContentLength = pdf_bytes.Length;

   return response;                  
Javascript

$.ajax({
    type: "POST",
    url: "/Reporting/GetLossSummary",
    data: { dataObj },
},
success: function (data) {
   if (data != null) {

    //I have tried this
    var file = new Blob([data], { type: 'application/pdf;base64' });
    var fileURL = URL.createObjectURL(file);
    window.open(fileURL, "LossSummaryReport");

    //which gives me a "failed to load pdf document" error

    //and I have tried this, which just renders a blank page
    window.open("data:application/pdf," + encodeURI(data)); 
  }
}
});

如果您有任何建议,我们将不胜感激。

因为您使用的是jsreport,在正常情况下,您可以使用更好地处理报告结果,并在浏览器中轻松显示它。但在您的情况下,您正在服务器中使用自定义url来呈现报表,因此jsreport browser sdk在这种情况下无法帮助您。相反,您需要使用jQuery ajax或普通XMLHttpRequest处理报告请求和响应

使用jQuery.ajax很难处理blob/二进制数据,您需要

/**
*
*jquery.binarytransport.js
*
*@说明。用于发出二进制数据类型请求的jQuery ajax传输。
*@version 1.0
*@作者亨利·阿尔格斯
*
*/
//将此传输用于“二进制”数据类型
$.ajaxTransport(“+二进制”,函数(选项、原始选项、jqXHR){
//检查blob/arraybuffer响应类型的条件和支持
if(window.FormData&&((options.dataType&&('options.dataType='binary'))| |(options.data&&((window.ArrayBuffer&&options.data instanceof ArrayBuffer)| |(window.Blob&&options.data instanceof Blob)| |)
{
返回{
//创建新的XMLHttpRequest
发送:函数(头、回调){
//设置所有变量
var xhr=new XMLHttpRequest(),
url=options.url,
type=options.type,
async=options.async | | true,
//blob或arraybuffer。默认值为blob
dataType=options.responseType | |“blob”,
data=options.data | | null,
username=options.username | | null,
password=options.password | | null;
xhr.addEventListener('load',function(){
变量数据={};
data[options.dataType]=xhr.response;
//进行回调并发送数据
回调(xhr.status、xhr.statusText、数据、xhr.getAllResponseHeaders());
});
open(类型、url、异步、用户名、密码);
//设置自定义标题
for(标题中的变量i){
setRequestHeader(i,headers[i]);
}
xhr.responseType=数据类型;
发送(数据);
},
中止:函数(){
jqXHR.abort();
}
};
}
});
但在处理请求/响应中的blob数据时,我更喜欢直接使用XHTMLRequest,因为它允许我以任何方式操纵响应

function sendReportRequest (dataObj, cb) {
  var xhr = new XMLHttpRequest()
  var data = JSON.stringify(dataObj)

  xhr.open('POST', 'http://url-of-your-server/' + '/Reporting/GetLossSummary', true)
  xhr.setRequestHeader('Content-type', 'application/json; charset=utf-8')
  xhr.responseType = 'arraybuffer'

  xhr.onload = function () {
    if (this.status >= 200 && this.status < 300) {
      var response = xhr.response
      var contentType = xhr.getResponseHeader('Content-Type')
      var dataView = new DataView(response)
      var blob

      try {
        blob = new Blob([dataView], { type: contentType })
        cb(null, blob)
      } catch (e) {
        if (e.name === 'InvalidStateError') {
          var byteArray = new Uint8Array(response)
          blob = new Blob([byteArray.buffer], { type: contentType })
          cb(null, blob)
        } else {
          cb(new Error('Can not parse buffer response'))
        }
      }
    } else {
      var error = new Error('request failed')

      error.status = xhr.status
      error.statusText = xhr.statusText

      cb(error)
    }
  }

  xhr.onerror = function () {
    var error = new Error('request failed')

    error.status = xhr.status
    error.statusText = xhr.statusText

    cb(error)
  }

  xhr.send(data)
}

sendReportRequest(dataObj, function (err, reportBlob) {
  if (err) {
    return console.error(err)
  }

  var reportFileUrl = URL.createObjectURL(reportBlob)

  window.open(reportFileUrl)
})
函数sendReportRequest(dataObj,cb){
var xhr=newXMLHttpRequest()
var data=JSON.stringify(dataObj)
xhr.open('POST','http://url-of-your-server/“+”/Reporting/GetLossSummary”,true)
setRequestHeader('Content-type','application/json;charset=utf-8')
xhr.responseType='arraybuffer'
xhr.onload=函数(){
如果(this.status>=200&&this.status<300){
var response=xhr.response
var contentType=xhr.getResponseHeader('Content-Type')
var dataView=新数据视图(响应)
var blob
试一试{
blob=新blob([dataView],{type:contentType})
cb(空,blob)
}捕获(e){
如果(e.name=='InvalidStateError'){
var byteArray=新的UINT8阵列(响应)
blob=新blob([byteArray.buffer],{type:contentType})
cb(空,blob)
}否则{
cb(新错误('无法分析缓冲区响应'))
}
}
}否则{
var error=新错误('请求失败')
error.status=xhr.status
error.statusText=xhr.statusText
cb(错误)
}
}
xhr.onerror=函数(){
var error=新错误('请求失败')
error.status=xhr.status
error.statusText=xhr.statusText
cb(错误)
}
发送(数据)
}
sendReportRequest(dataObj,函数(err,reportBlob){
如果(错误){
返回控制台。错误(err)
}
var reportFileUrl=URL.createObjectURL(reportBlob)
window.open(reportFileUrl)
})

使用这段代码,您应该能够请求一个pdf文件,并将其显示在浏览器的新窗口中

您没有将文档/内容添加到响应中您还混合了mime类型/数据uri格式。如果返回的数据是ArrayBuffer,则将blob的mime类型仅设置为类型:“application/pdf”。如果您选择数据uri方法,还可以指定base64(尽管它是默认值):window.open(“data:application/pdf;base64,”+…@daddygames-您说我没有将文档/内容添加到响应中是什么意思?API中的内容位于“base64EncodedPDF”中并且被添加到api中的响应对象。@K3N-即使我切换了上面提到的内容,这两种情况都不起作用。抱歉,我忽略了代码。您是否检查了Javascript成功函数中的数据变量?该变量是否作为PDF文件的base64表示形式返回?或者它至少看起来像base64字符串值e?您好,感谢您提供的上述内容。但是我需要能够发送JSON数据,而且上面的调用似乎不接受JSON数据。根据本网站,将在XHR请求中发送一个数据体。这可以是:一个文档,在这种情况下,它在发送之前被序列化。一个BodyInit,根据Fetch规范,它可以是一个Blob、BufferSource、FormData、URLSearchParams、ReadableStream或USVString对象。是的,
sendReportRequet
中的代码正在发送json数据。如果仔细查看developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/send网站,您可以看到
function sendReportRequest (dataObj, cb) {
  var xhr = new XMLHttpRequest()
  var data = JSON.stringify(dataObj)

  xhr.open('POST', 'http://url-of-your-server/' + '/Reporting/GetLossSummary', true)
  xhr.setRequestHeader('Content-type', 'application/json; charset=utf-8')
  xhr.responseType = 'arraybuffer'

  xhr.onload = function () {
    if (this.status >= 200 && this.status < 300) {
      var response = xhr.response
      var contentType = xhr.getResponseHeader('Content-Type')
      var dataView = new DataView(response)
      var blob

      try {
        blob = new Blob([dataView], { type: contentType })
        cb(null, blob)
      } catch (e) {
        if (e.name === 'InvalidStateError') {
          var byteArray = new Uint8Array(response)
          blob = new Blob([byteArray.buffer], { type: contentType })
          cb(null, blob)
        } else {
          cb(new Error('Can not parse buffer response'))
        }
      }
    } else {
      var error = new Error('request failed')

      error.status = xhr.status
      error.statusText = xhr.statusText

      cb(error)
    }
  }

  xhr.onerror = function () {
    var error = new Error('request failed')

    error.status = xhr.status
    error.statusText = xhr.statusText

    cb(error)
  }

  xhr.send(data)
}

sendReportRequest(dataObj, function (err, reportBlob) {
  if (err) {
    return console.error(err)
  }

  var reportFileUrl = URL.createObjectURL(reportBlob)

  window.open(reportFileUrl)
})