I would like to add a filename to my Blob file, but I don't really know how to do it, here is my code for the moment :
onClick() {
var myHeader = new Headers();
myHeader.append('Content-Type', 'text/plain');
fetch(this.props.url, {
method: 'POST',
headers: myHeader,
body: JSON.stringify(this.state.api_arg)
}).then(response => {
const filename = getFileName(response.headers.get('Content-Disposition'))
response.blob().then(myBlob => {
const fileUrl = URL.createObjectURL(myBlob)
console.log(fileUrl)
window.open(fileUrl)
})
})
}
my filename is stocked in a variable.
The answer of Niels was incomplete, to handle filename in blob you have to do it that way:
const file = new File([myBlob], filename)
const url = URL.createObjectURL(myBlob);
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', filename);
document.body.appendChild(link);
link.click();
Related
How to download a file from an API response which is in a different format ?
await axios.get(`/dashboard/reportdownload/?file_name=242424242.pdf`,{
headers: {
"Authorization": `Bearer 767958756576576576jgjhgjhg`
}
})
.then((res) => {
console.log(res?.data);
});
In response I am getting
How do download it with reactjs
You need to check if the response from the API is of type blob, then convert it. For example, if it is clear you are expecting a PDF response, try this:
await axios.get(`/dashboard/reportdownload/?file_name=242424242.pdf`, {
headers: {
'Authorization': `Bearer 767958756576576576jgjhgjhg`
}
})
.then((response) => {
let fileName = '242424242.pdf';
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
// IE variant
window.navigator.msSaveOrOpenBlob(
new Blob([response.data], {
type: 'application/pdf',
encoding: 'UTF-8'
}),
fileName
);
} else {
const url = window.URL.createObjectURL(
new Blob([response.data], {
type: 'application/pdf',
encoding: 'UTF-8'
})
);
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', fileName);
document.body.appendChild(link);
link.click();
link.remove();
}
});
Here is the Javascript code
function DownloadFromUrl(url, mime) {
axios({
url: url,
method: 'GET',
responseType: 'blob', // important
}).then((response) => {
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', 'file.' + mime);
document.body.appendChild(link);
link.click();
});
}
$("#dl_file").click(() => {
DownloadFromUrl("http://www.africau.edu/images/default/sample.pdf", "pdf");
});
Here is HTML code
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.js">
<button id="dl_file">
Download File
</button>
Here is the jsfiddle link : https://jsfiddle.net/maayuresh/uzfsgjet/2/
So I did this not too long ago, also with Axios but had some slightly different settings.
The main thing is that the responseType sent in the request was set to 'arraybuffer' and when processing the response I provided the mimeType when creating the Blob new Blob([result.data], { type: 'application/pdf' });.
I'm trying to download pdf file from rest api using those two methods:
download(): ng.IPromise<Blob> {
return this.$http.get<ArrayBuffer>(this.urls.getUrl())
.then(response => {
return new Blob([response.data], {type: 'application/pdf'});
}
)
}
this.service.download().then( file => {
var a = document.createElement("a"),
url = URL.createObjectURL(file);
open(url)
a.href = url;
a.download = 'invoice';
document.body.appendChild(a);
a.click();
setTimeout(function() {
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}, 0);
}
And there appears to be some problem with the encoding of created Blob. If I call this endpoint from Postman and select "save response" then "save to a file", I get the correct pdf. When I use the presented code, file seems to be incorrectly encoded (opened with vim has generally similar structure, but different symbols).
In service you can use httpOptions like this:
download() {
const httpOptions = {
responseType: 'blob' as 'json',
};
return this.http.get<any>(
ServerUrl + `/api/getfile`,
httpOptions
);
}
also on you component you can call service and download the pdf like this:
this.api.download().subscribe(
(idata) => {
let blob = new Blob([idata], { type: 'application/pdf'
});
var downloadURL = window.URL.createObjectURL(idata);
var link = document.createElement('a');
link.href = downloadURL;
link.download = 'invoice.pdf';
link.click();
},
async (err) => {
}
);
I have a problem when downloading files from my dropbox.
While using the type 'text/csv' I can download and view txt files.
Chaning the type to 'image/jpeg' or 'application/pdf' and download the filetype gives me blank file.
Am I on the right track here or is there another way this should be done?
main.service.ts
downloadFile(id) {
const headers = new Headers();
headers.append('Authorization', 'Bearer ' + this.accessToken);
const path = `{"path": "${id}"}`;
headers.append('Dropbox-API-Arg', path);
return this.http.post('https://content.dropboxapi.com/2/files/download',
null, { headers: headers });
}
main.component.ts
downloadFileBlob(data: any, name) {
const blob = new Blob([data], { type: 'image/jpeg' });
const url = window.URL.createObjectURL(blob);
window.open(url);
}
saveFile(id, name) {
this.dropbox.downloadFile(id).subscribe((data: any) => {
this.downloadFileBlob(data._body, name); });
}
Turns out I was going at this the wrong way.
Dropbox github has an example of using sharingGetSharedLinkFile, which works about the same as filesDownload.
Replace sharingGetSharedLinkFile with filesDownload and provide a file path instead of the URL.
Something like this:
function downloadFile() {
var ACCESS_TOKEN = (<HTMLInputElement> document.getElementById('access-
token')).value;
var SHARED_LINK = (<HTMLInputElement> document.getElementById('shared-
link')).value;
var dbx = new Dropbox.Dropbox({ accessToken: ACCESS_TOKEN });
dbx.filesDownload({path: SHARED_LINK})
.then(function(data) {
var downloadUrl = URL.createObjectURL((<any> data).fileBlob);
var downloadButton = document.createElement('a');
downloadButton.setAttribute('href', downloadUrl);
downloadButton.setAttribute('download', data.name);
downloadButton.setAttribute('class', 'button');
downloadButton.innerText = 'Download: ' + data.name;
document.getElementById('results').appendChild(downloadButton);
});
}
In order to force download PDF from server I tried to use axios and native xhr object. The reason is that I have to send post request, because I pass too much data to server, so the option with simple link (like site.ru/download-pdf won't work for me).
Even though I finally managed to do this with Xhr, I still don't have a clue why axios way doesn't work.
Here is how I do this with xhr and it works for me:
let xhr = new XMLHttpRequest()
xhr.open('POST', Vue.config.baseUrl + `order-results/${id}/export-pdf`, true)
xhr.setRequestHeader("Authorization", 'Bearer ' + this.token())
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded")
xhr.responseType = 'arraybuffer'
xhr.onload = function(e) {
if (this.status === 200) {
let blob = new Blob([this.response], { type:"application/pdf" })
let link = document.createElement('a')
link.href = window.URL.createObjectURL(blob)
link.download = 'Results.pdf'
link.click()
}
};
xhr.send("data=" + data);
Here is "axios-way" and I actually get PDF with correct number of pages, but they are all empty:
axios.post(`order-results/${id}/export-pdf`, {
data,
responseType: 'arraybuffer'
}).then((response) => {
let blob = new Blob([response.data], { type:"application/pdf" })
let link = document.createElement('a')
link.href = window.URL.createObjectURL(blob)
link.download = 'Results.pdf'
link.click()
})
Axios is already configured to send Authorization token.
I put Application/x-www-form-urlencoded in xhr because otherwise I couldn't get data in server side.
Even though xhr works, I'd prefer to use axios since I use it everywhere and I'm just curios what I'm doing wrong. I tried different solutions, and only native xhr did the job.
The following works for me:
axios.post("http://localhost:8080/reports/my-report/",
data,
{
responseType: 'arraybuffer',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/pdf'
}
})
.then((response) => {
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', 'file.pdf'); //or any other extension
document.body.appendChild(link);
link.click();
})
.catch((error) => console.log(error));
Let me know if this helps.
Cheers!
For whatever reason the pdf is downloading but any content passed is not appearing resulting in a blank pdf.
I found this code snippet that is similar but results in a pdf with content.
axios({
url: '/pdf',
method: 'GET',
responseType: 'blob', // important
}).then((response) => {
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', 'file.pdf');
document.body.appendChild(link);
link.click();
});
there was some feedback stating that it didnt work on IE 11, I have not tested it but a solution was posted using FileSaver.js
axios({
url: '/pdf',
method: 'GET',
responseType: 'blob', // important
}).then((response) => {
FileSaver.saveAs(new Blob([response.data]));
});
There is a special responseType: 'blob':
axios.post(`order-results/${id}/export-pdf`, {
data,
responseType: 'blob'
}).then((response) => {
let link = window.URL.createObjectURL(blob)
link.download = 'Results.pdf'
link.click()
})
Or you can use window.open method:
axios.post(`order-results/${id}/export-pdf`, {
data,
responseType: 'blob'
}).then((response) => {
window.open(URL.createObjectURL(response.data));
})
You're getting empty PDF 'cause no data is passed to the server. You can try passing data using data object like this
axios.post(`order-results/${id}/export-pdf`, {
data: {
firstName: 'Fred'
},
responseType: 'arraybuffer'
}).then((response) => {
console.log(response)
let blob = new Blob([response.data], { type: 'application/pdf' } ),
url = window.URL.createObjectURL(blob)
window.open(url); // Mostly the same, I was just experimenting with different approaches, tried link.click, iframe and other solutions
});
By the way I gotta thank you so much for showing me the hint in order to download pdf from response. Thank ya :)
var dates = {
fromDate: 20/5/2017,
toDate: 25/5/2017
}
The way in which I have used is,
axios({
method:'post',
url:'/reports/interval-dates',
responseType:'arraybuffer',
data: dates
})
.then(function(response) {
let blob = new Blob([response.data], { type: 'application/pdf' } );
let link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = 'Report.pdf';
link.click();
});