【发布时间】:2022-01-13 16:23:43
【问题描述】:
我正在尝试使用以下代码在单击href 时调用 REST GET API。我需要在 HTTP GET 请求中发送我的自定义标头。我希望 GET API 返回的 pdf 文件在单击 href 时在浏览器的新选项卡中打开,而原始页面保持在其选项卡中。
当我使用下面的代码时,它会在新选项卡中打开相同的页面 URL。当我查看在浏览器的 Javascript 控制台下进行的网络调用时,它确实表明 API 是使用所需的标头调用的。但浏览器本身不会显示。
<!DOCTYPE html>
<html>
<head>
<title> A jQuery click href </title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
$(document).ready(function() {
$('#click_href').click(function() {
$.ajax({
url: 'http://myserver:8080/path/download?a=A&b=B&filename=file.pdf',
type: 'GET',
dataType: 'pdf',
beforeSend: function (xhr) {
xhr.setRequestHeader('CLIENT_ID', 'WEB_APP');
},
success: function (response) {
}
})
});
});
</script>
</head>
<body>
<h1> Demonstration for jQuery click href </h1>
<a href="#" id="click_href" target="_blank">Test by Curious Brain</a>
</body>
</html>
更新
这就是 Spring Boot REST 控制器返回 PDF 的方式。如果我在浏览器窗口中尝试直接下载 URL,则 PDF 会显示在浏览器中。
@CrossOrigin
@RequestMapping(path = "/download", method = RequestMethod.GET, produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<InputStreamResource> download(
@RequestParam("a") String a,
@RequestParam("b") String b,
@RequestParam("filename") String fileName) throws IOException {
FileSystemResource pdfFile = new FileSystemResource(reportBaseDir + "/" + a + "/" + b + "/" + fileName);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType(MediaType.APPLICATION_PDF_VALUE));
headers.setAccessControlAllowMethods(Arrays.asList(HttpMethod.GET));
headers.setAccessControlAllowHeaders(Arrays.asList("Content-Type"));
headers.setContentDisposition(ContentDisposition.builder("inline").filename(fileName).build());
headers.setCacheControl("no-cache, no-store, must-revalidate");
headers.setPragma("no-cache");
headers.setExpires(0L);
headers.setContentLength(pdfFile.contentLength());
return new ResponseEntity<InputStreamResource>(
new InputStreamResource(pdfFile.getInputStream()), headers, HttpStatus.OK);
}
根据下面给出的回复,我将我的 HTML 代码更新为:
<!DOCTYPE html>
<html>
<head>
<title> A jQuery click href </title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
$(document).ready(function() {
$('#click_href').click(function(e) {
e.preventDefault();
$.ajax({
url: 'http://myserver:8080/path/download?a=A&b=B&filename=file.pdf',
type: 'GET',
dataType: 'pdf',
beforeSend: function (xhr) {
xhr.setRequestHeader('CLIENT_ID', 'WEB_APP');
},
success: function (response) {
window.open("data:application/pdf," + escape(response), '_blank');
}
})
});
});
</script>
</head>
<body>
<h1> Demonstration for jQuery click href </h1>
<a href="#" id="click_href">Test by Curious Brain</a>
</body>
</html>
即便如此,我仍然可以看到对下载 URL 进行了调用,但没有任何反应。我希望当单击 href 链接时,pdf 文件显示在浏览器的新选项卡中。
来自浏览器的 Javascript 控制台的网络跟踪:
Summary
URL: http://myserver:8080/path/download?a=A&b=B&filename=file.pdf
Status: 200
Source: Network
Address: <some ip>:8080
Initiator:
jquery.min.js:2:82618
Request
GET /path/download HTTP/1.1
Accept: */*
Origin: null
Accept-Encoding: gzip, deflate
Host: myserver:8080
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Safari/605.1.15
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
CLIENT_ID: WEB_APP
Response
HTTP/1.1 200
Access-Control-Allow-Origin: *
Content-Type: application/pdf
Pragma: no-cache
Content-Disposition: inline; filename="file.pdf"
Keep-Alive: timeout=60
Access-Control-Allow-Methods: GET
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Access-Control-Allow-Headers: Content-Type
Cache-Control: no-cache, no-store, must-revalidate
Date: Thu, 13 Jan 2022 21:19:02 GMT
Content-Length: 387717
Connection: keep-alive
Vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers
Query String Parameters
a: A
b: B
filename: file.pdf
更新 2:
这是我能做到的最接近的。但这只会下载文件。我尝试了window.open(…),但没有在浏览器中打开文件。
<!DOCTYPE html>
<html>
<head>
<title> A jQuery click href </title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
$(document).ready(function() {
$('#click_href').click(function(e) {
e.preventDefault();
$.ajax({
//cache: false,
type: 'GET',
url: 'http:/myserver:8080/path/download?a=A&b=B&filename=file.pdf',
//contentType: false,
//processData: false,
data: 'native',
beforeSend: function (xhr) {
xhr.setRequestHeader('CLIENT_ID', 'WEB_APP');
},
xhrFields: {
responseType: 'blob'
},
success: function (response, status, xhr) {
var filename = '';
var disposition = xhr.getResponseHeader('Content-Disposition');
alert(disposition);
if (disposition) {
filename = disposition.split('"')[1];
alert(filename);
}
var linkelem = document.createElement('a');
var blob = new Blob([response], { type: 'application/octet-stream' });
var downloadUrl = window.URL.createObjectURL(blob);
var a = document.createElement("a");
a.href = downloadUrl;
a.download = filename;
document.body.appendChild(a);
a.target = "_blank";
//window.open(a);
a.click();
}
});
});
});
</script>
</head>
<body>
<h1> Demonstration for jQuery click href </h1>
<a href="#" id="click_href">Test by Curious Brain</a>
</body>
</html>
【问题讨论】:
-
如果我用一些随机的 pdf 填充运行最后一段代码(应该打开 PDF 的代码),它会在浏览器中正确打开。因此,您的 PDF 或您为它们提供服务的方式必须有一些时髦的东西。我无法重现该问题,这表明问题可能与您目前显示的代码无关。你能创建一个runnable minimal reproducible example吗?
-
我让它工作了。问题在于 JavaScript 代码中的
application/octet-stream。 mime 类型强制下载文件。当我将其更改为application/pdf时,文件在浏览器中打开而不是下载。我将很快发布完整的解决方案和调查结果。一个奇怪的事情仍然是一个谜(对我的要求并不重要)是浏览器地址栏显示blob:null/6af2f4a4-ca4d-42fa-9962-c54ae3cd357c,我不知道如何让它显示文件名。
标签: javascript html jquery