简体   繁体   中英

HTML anchor tag's onclick not working with REST GET API call

I am trying the below code to call a REST GET API on click of href . I need to send my custom headers in the HTTP GET request. I want the pdf file returned by GET API to be opened in a new tab in the browser when the href is clicked while the original page stays as is in its tab.

When I use the code below, it opens the same page URL in a new tab. When I look at the Network call made under browser's Javascript console, it does show that the API was invoked with the required headers. But the browser itself doesn't display that.

<!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>

UPDATE

This is how the PDF is returned by Spring Boot REST controller. If I try the direct download URL in a browser window, the PDF is displayed in the browser.

@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);
    }

Following the responses given below, I updated my HTML code to this:

<!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>

Even then, I can see that a call is made to the download URL but nothing happens. I want the pdf file to be displayed in a new tab in the browser when the href link is clicked.

Network trace from browser's Javascript console:

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

UPDATE 2:

This is the closest I could bring this to. But this only downloads the file. I tried window.open(…) but that doesn't open the file in the browser.


<!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>

The browser is opening the current page in a new window because that is what the link does.

href="#" means "the top of the current page" and target="_blank" means "in a new window or tab".

The JavaScript isn't calling preventDefault on the event object, so that behaviour isn't prevented.


The Ajax request is a completely separate HTTP request which you run when the link is clicked.

It makes the HTTP request.

The data is returned to JS.

The success function is run.

The data is passed into the response variable.

And then you do … nothing.

If you want to do something with the data from the Ajax request then you have to actually do something .

Perhaps something along the lines of the answers to this question .

Not really sure what response is return by your API call, if its returning the pdf file path then you can simply make use of window.open();

<script>
$(document).ready(function() {
    $('#click_href').click(function(e) {
        e.preventDefault(); // this is to stop your page from reloading
        $.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) {
            // If your response if url then you can use
            window.open(response, '_blank');

           // IF your response is base64 PDF data then you can use something like 
          window.open("data:application/pdf," + escape(response), '_blank'); 

        }
    })
    });
});
</script>

Also you need to remove target="_blank" from your original a tag

Using the following markup should do what you want, without any additional JavaScript:

<a href="http://myserver:8080/path/download?a=A&b=B&filename=file.pdf"
   target="_blank">Open pdf</a>

Potential checks, for others with the same problem:

  1. Content-Disposition response header exists and is set to inline (to open the file in browser) and attachment (to save the file on disk). ✔️
  2. The browser is capable of opening the file type (if not capable, it will download the file) ✔️
  3. Content-Type response header should be correct for the file type. ✔️
  4. The file URL is correct (including protocol) ✔️
  5. (if applicable): any browser setting (native or via extensions) for that particular file type. In the case of PDFs: chrome://settings/content/pdfDocuments

All of the above are true in your case, except last, which I don't know. However, you're saying you can open the .pdf in browser if you access the link directly, which means you probably have "Open PDFs in Chrome" selected.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM