New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Missing documentation for downloading binary files #448
Comments
+1 for this. I was really lost until I found this issue. |
me too! thank you @demetriusnunes !! |
In case other stumple upon this thread when looking for an answer to serve external images from node using axios and express without having to save the external file to disk first. To clarify where to put responseType parameter as stated by @demetriusnunes , here's an example: var imageurl = 'https://avatars2.githubusercontent.com/u/5302751?v=3&s=88';
axios.get(imageurl, {
responseType: 'arraybuffer'
})
.then(function (response) {
res.type('image/jpeg');
res.end( response.data, 'binary' );
}); Happy coding 😄 |
And if you were like me, and you stumble upon this thread looking for a method to download images client-side, here's an example:
|
@bjunc Thank you! Wish I would have discovered this thread 2 hours ago. |
What about when downloading excel files? |
@vinikatyal Have you solved your problem? |
@imzyf @vinikatyal Have you solved your problem? |
@2ming no, I use GET request to download excel file. |
...and excels in a zipped file...? Tried many approach nothing works from browser... |
@vinikatyal @imzyf did you solve the excel problem? I'm facing with the same here. |
I solved the excel problem using
|
yes, same here, but what about the name? Let's say you want to pass the name to frontend... |
@Itachi-Uchiha78 You should somehow resolve that in the backend. Why not always zip it and just download a zip file? |
because customers don't want unzip a single file....they just want it download and open.... |
@Itachi-Uchiha78 You should ask how to solve your issue in Stack Overflow. This is not an issue with axios. |
Thank you for this thread @demetriusnunes , half a day to find this. |
I use js-file-download, matching the filename given from backend. import fileDownload from 'js-file-download'
import axios from 'axios'
let res = await axios({
// ...
responseType: 'blob'
})
let disposition = res.headers['content-disposition']
let filename = decodeURI(disposition.match(/filename="(.*)"/)[1])
fileDownload(res.data, filename) Note that if you have to handle error in json while downloading files in blob: |
And if you were like me, and you stumble upon this thread looking for a method to download images client-side, and would like to avoid FileReader(); due to number of reasons here's an example: import axios from 'axios'
axios.request({
url: 'http://mydomain.com/path/myimage.jpeg',
responseType: 'blob',
})
.then(response => response.data)
.then(blob => URL.createObjectURL(blob))
.then(src => this.setState({ src })) // OR imageEl.setAttribute("src", src);
.catch(onFail); Don't forget to cleanup the image once you don't need it, for ex: componentWillUnmount() {
if (this.state.src !== null) {
URL.revokeObjectURL(this.state.src)
}
} |
And is there a way to download the file directly to disk as a stream, instead of first getting it into response.data? Hopefully, with a "resume download" happening automagically? |
For me this worked, and it's also passing Authorisation headers which i set globally elsewhere @mauzepeda thank you for your comment example it helped me solve the issue of opening in a new window and changing my backend code.
|
This is money 💰. Thanks for reporting on this. Just in case someone else was doing something similar to me, this is what I did //initial request
const config = {
params,
url: `${endPoint}`,
headers: {
'Accept': 'application/vnd.ms-excel'
},
responseType: 'blob'
};
return request(endPoint, config)
.then(data => {
let blob = new Blob([data], {type: ''});
const blobHref = window.URL.createObjectURL(blob);
//... dispatching actions to download the file within a react app
}) |
I'm puzzled, I have to download any possible file but it keeps corrupting my binary files.. I tried download as blob, array buffer,... anyone got any idea? I noticed a lot of people including the exact file type they are expecting as a header which is not possible for me :/ axios(url, {
method: 'GET',
responseType: 'arrayBuffer',
headers: {
'x-user': getEnvironment().DB_USER,
'x-password': getEnvironment().DB_PASSWORD
}
})
.then(response => {
res.json({
error: null,
data: response.data
})
})
.catch(e => {
console.log(e, 'error download')
res.json({error: e.message, documents: []})
}) Fetching the files with postman actually works with these headers so that's not the issue |
@Pixelatex, not sure if this might be the issue or a typo, but you should set the responseType as |
autocorrect in fact, sadly it is not that easy a fix :/ |
The workaround is worth a try: #815 (comment) |
I was one of the unlucky ones as well.. Here's my solution:
|
You don't think this should be treated as a bug? Why by default any request has be treated as utf8 string? I think axios should be check 'Content-type' if is binary file (octet-stream, jpeg, zip, etc) and not to stringify the response: Line 197 in ccc7889
I think this implementation will avoid a lot of bugs in projects that are using Axios. |
Was thinking about something like
based on what @mauzepeda wrote. But how can I use the image to be downloaded as name instead of a hardcoded one? And is / the best header for all sorts of images? |
I really struggle to understand why one has to know the type of response before sending the request. Since the HTTP spec allows the server to respond with anything he wants, and treat |
As pointed out this is a fairly easy fix just using basics of HTTP, just check the content-type response header and/or the accept header instead of require the requestType option. At the same time I think I understand the idea of responseType as way of making the library more flexible, and I do agree on it as I think flexibility bring more goods than constant guess. Now for cases where the implementation is/need-to-be generic and there is no such luxury we can still guess based on request and response and the media type associate with Accept and Content-Type headers, the difference is that this guess will by based on our business needs which is for sure narrower than the possible scenarios this library should account for. Anyway my workaround is that:
determineResponseType(req) {
let answer = 'arraybuffer';
if (req.headers.accept) {
const match = /.+\/(.+)/gi.exec(req.headers.accept);
if (['javascript', 'json', 'plain', 'csv', 'xml', 'css', 'html',].some(st => match[1] == st)) {
answer = match[1];
}
}
return answer;
}
extractResponseData(res) {
let answer = res.data;
if (res.headers['content-type']) {
const match = /.+\/(.+)/gi.exec(res.headers['content-type']);
if (['javascript', 'json', 'plain', 'csv', 'xml', 'css', 'html',].some(st => match[1] == st)) {
answer = answer.toString('utf-8');
}
}
return answer;
} After this we have the proper response data and setting the proper Content-Type on your client response, whatever is the framework you use, just copy/cherrypick server response header to client response headers and we will have proper rendering/download on our client. i.e. if we are using express we can simply do something like this: let responseData = this.extractResponseData(serverResponse);
clientResponse.status(serverResponse.status);
Object.entries(serverResponse.headers || {}).forEach(entry => clientResponse.set(entry[0], entry[1]));
clientResponse.send(responseData); In short I believe this is not really an issue of the library but a question of interpretation so here the greater good of the library purpose should prevail. |
thanks, really solved my problem |
Nice |
我试了上面的所有方法,发现都不行 |
You can make is simpler:
|
I had to do a lot of trial and error, until I found out that adding "responseType" as "arraybuffer" would do the trick.
The text was updated successfully, but these errors were encountered: