Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
402 views
in Technique[技术] by (71.8m points)

javascript - How to handle file downloads with JWT based authentication?

I'm writing a webapp in Angular where authentication is handled by a JWT token, meaning that every request has an "Authentication" header with all the necessary information.

This works nicely for REST calls, but I don't understand how I should handle download links for files hosted on the backend (the files reside on the same server where the webservices are hosted).

I can't use regular <a href='...'/> links since they won't carry any header and the authentication will fail. Same for the various incantations of window.open(...).

Some solutions I thought of:

  1. Generate a temporary unsecured download link on the server
  2. Pass the authentication information as an url parameter and manually handle the case
  3. Get the data through XHR and save the file client side.

All of the above are less than satisfactory.

1 is the solution I am using right now. I don't like it for two reasons: first it is not ideal security-wise, second it works but it requires quite a lot of work especially on the server: to download something I need to call a service that generates a new "random" url, stores it somewhere (possibly on the DB) for a some time, and returns it to the client. The client gets the url, and use window.open or similar with it. When requested, the new url should check if it is still valid, and then return the data.

2 seems at least as much work.

3 seems a lot of work, even using available libraries, and lot of potential issues. (I would need to provide my own download status bar, load the whole file in memory and then ask the user to save the file locally).

The task seems a pretty basic one though, so I'm wondering if there is anything much simpler that I can use.

I'm not necessarily looking for a solution "the Angular way". Regular Javascript would be fine.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Here's a way to download it on the client using the download attribute, the fetch API, and URL.createObjectURL. You would fetch the file using your JWT, convert the payload into a blob, put the blob into an objectURL, set the source of an anchor tag to that objectURL, and click that objectURL in javascript.

let anchor = document.createElement("a");
document.body.appendChild(anchor);
let file = 'https://www.example.com/some-file.pdf';

let headers = new Headers();
headers.append('Authorization', 'Bearer MY-TOKEN');

fetch(file, { headers })
    .then(response => response.blob())
    .then(blobby => {
        let objectUrl = window.URL.createObjectURL(blobby);

        anchor.href = objectUrl;
        anchor.download = 'some-file.pdf';
        anchor.click();

        window.URL.revokeObjectURL(objectUrl);
    });

The value of the download attribute will be the eventual file name. If desired, you can mine an intended filename out of the content disposition response header as described in other answers.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...