Javascript 动态PDF并打开新窗口而不是下载
我有一个web api,它以编码字节数组的形式返回JSReport。无论我如何尝试读取字节数组,我都会收到一个黑屏或一条错误消息,上面写着“下载pdf失败”。如果我创建一个隐藏的锚定标记并下载pdf,它就可以正常工作。但是,我不希望用户下载它,我更希望他们可以直接从浏览器中查看它 WEB API调用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
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)
})