I want to save the svg file provided by the server as a png file with JavaScript.
I think the file format is wrong, how can I download it?
This is the code to download the svg file. I wonder how to fix it.
const accessCookie = getAccessTokenCookie();
axios({
url: `${baseUrl}/${this.Qrid}`,
method: 'GET',
// responseType: 'arraybuffer',
headers: {
Authorization: `Bearer` + accessCookie,
},
}).then(response => {
var file = new Blob([response.data], { type: 'image/svg' });
const fileURL = URL.createObjectURL(file);
const link = document.createElement('a');
link.href = fileURL;
link.download = 'qr' + this.$date().format('YYYY.MM.DD_h_m_s') + '.svg';
link.click();
console.log(response);
});
Related
I am getting the attachment body using the Rest API.
var config = {
method: 'get',
url: '<Domanin>/services/data/v48.0/sobjects/Attachment/00PD000000HQD68MAH/Body',
headers: {
'Authorization': `Bearer ${
accessToken
}`,
'content-type':'application/pdf'
},
};
let rawData = await axios(config);
rawData = rawData.data
I am getting the PDF data in this format
%PDF-1.5
%ÓôÌá
1 0 obj
<<
In the client side I am trying to make this as a downloadable file but I am getting blank pdf. The actual pdf contains 2 pages the downloaded pdf contains two pages as well but they are blank.
Client Side Code:
var downloadLink = document.createElement('a');
downloadLink.target = '_blank';
downloadLink.download = 'test.pdf';
// convert downloaded data to a Blob
var blob = new Blob(([rawData]), {type: 'application/pdf'});
// create an object URL from the Blob
var downloadUrl = URL.createObjectURL(blob);
// set object URL as the anchor's href
downloadLink.href = downloadUrl;
// append the anchor to document body
document.body.append(downloadLink);
// fire a click event on the anchor
downloadLink.click();
Please let me know what is wrong with the above logic
Please specify responseType: 'arraybuffer' in request config. Modify your config object to
{
method: 'get',
url: '<Domanin>/services/data/v48.0/sobjects/Attachment/00PD000000HQD68MAH/Body',
headers: {
'Authorization': `Bearer ${
accessToken
}`
},
'responseType': 'arraybuffer'
};
I want to download a zip file with a size of 300mb, I do it in Node.js with stream (so the download is byte by byte).
request('https://...').pipe(res);
The problem is I need to send a token to download this file in the header.
How to do it? Because I try to do it with this code:
let a = document.createElement('a');
a.href = `/api/download`;
a.target = '_blank';
a.download = 'test.zip';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
console.log('done');
It works when I turn off the token required. (but I need to send this token).
I also try this code:
axios({
url: 'http://localhost:5000/api/download',
method: 'GET',
responseType: 'blob', // important
headers: {
Authorization: "Bearer <insert_your_JWT_here>"
}
}).then((response) => {
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', 'file.zip');
document.body.appendChild(link);
link.click();
});
But what this does is download the file (300mb) and after it's downloaded, it begins to download to the disk (this is bad).
So, how to download file as stream and with token?
So, in your code i don't see place where you keep your token.
You can use bearer
Try simple example:
axios({
url: 'http://localhost:5000/api/download',
method: 'GET',
responseType: 'blob', // important
headers: {
Authorization: "Bearer <insert_your_JWT_here>"
}
}).then((response) => {
//your code
});
On Node Server i have this code . Its basically sending the browser POST data to api server and recieves a file as chunk data and the same data is send back to browser via pipe response . But the issue is the api reponse is correct and i can write the file using nodejs locally but it doesnt push download file in browser
router.post('/MyURLOnNODE', function (req, res) {
var MyJsonData = { some Data };
res.writeHead(200, {'Content-disposition': 'attachment; filename=fileArchive.tgz','Content-Type': 'application/force-download'});
try {
request({
url: 'SomeAPI Url', //URL to hit
method: 'POST',
json: MyJsonData
}).pipe(res);
} catch(e) {
console.log("Pipe error",e);
}
console.log("File Streaming Called ",MyJsonData)
}
);
Client Side Code ...This was an attempt to create a blob and use it on urlObject. but the downloaded file is corrupted when i checked in hex.
$http({
method: 'POST',
url: 'MyURLOnNODE',
data: PostData, //forms user object
headers: {
'Content-Type': 'application/json'
}
})
.then(function (data) {
var response=data.data;
var id = Flash.create('success', "Folder Archieved", 5000);
var a = document.getElementById('arch');
a.href = URL.createObjectURL(new Blob([response]));
a.download = "FolderMe.tgz";
a.type='application/octet-stream '
a.click();
}
So is there any solution to this ? either on NodeJs Side or On browser
Update : https://stackoverflow.com/a/7969061/7078299
This thread says its hard to convert an ajax request to download file. So i need to work on client on using urlobject. But blob isnt working with stream data. How to solve it
You can use a node module called file-saver and use saveAs method provided by it and download the file on the client side.
First npm install file-saver;
You can use it as
import {saveAs} from 'file-saver';
and inside your then block you need to add this line
saveAs(new Blob([response]), <your file name>)
It will auto-download your file.
i fixed the issue by adding a reponseType on Client Side Code. Now the blob and ObjectUrl works correctly
$http({
method: 'POST',
url: 'MyUrl',
data: PostData, //forms user object
headers: {
'Content-Type': 'application/json'
},
responseType: 'arraybuffer'
})
.then(function (response) {
console.log(response);
var headers = response.headers();
var blob = new Blob([response.data],{type:headers['content-type']});
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = "Archive.tgz";
link.click();
});
I created a download button that downloads the file on click. The problem is when I click the download button, I'm able to see the content that I want to download by using Chrome inspect -> Network -> Response but it is not opening a window to save the file to my PC.
For example, I'm trying to download text.txt which contains multiple lines of MY FILE string. I'm able to see it on Response tab but how can I download the .txt file.
Relevant React Code:
<button onClick={(e) => downloadHandler(e)}>Download</button>
let downloadHandler = (e) =>{
const fileName = e.target.parentElement.id;
fetch('http://localhost:3001/download',{
method: 'post',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({id: fileName})
})
}
Relevant Backend Code:
const uploadFolder = `${__dirname}` + `\\uploads\\`;
app.post('/download', function(req, res){
let fileName = req.body.id; // example output: 'dog.jpg'
res.download(uploadFolder+fileName, fileName); // Set disposition and send it.
});
The idea is that I will feed fileName to backend and then download it with res.download(uploadFolder+fileName, fileName); line. I think im suppose to use window.open('/download') but that just opens the homepage on a new tab or maybe I am just placing it wrong.
Okay, I have managed to solve my issue. three main modifications were made to make this code and idea work.
Changing the request from POST to GET. Another
StackOverflow thread also mentions this.
Using axios() instead of fetch().
Creating Blob object from the res.download(filePath, fileName) response value.
Anyone else having this problem with the React Code part should check this Github link.
Final State of the React function posted in the question
let downloadHandler = (e) =>{
const fileName = e.target.parentElement.id;
axios({
method: 'get',
url: 'http://localhost:3001/download/'+fileName,
responseType: 'blob',
headers: {},
})
.then((res) => {
const url = window.URL.createObjectURL(new Blob([res.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', fileName);
document.body.appendChild(link);
link.click();
})
.catch((error) => {
alert(error);
})
}
Final State of the backend code posted in the question
const uploadFolder = `${__dirname}` + `\\uploads\\`;
app.get('/download/:filename', function(req, res){
let fileName = req.params.filename
const filePath = uploadFolder+fileName;
res.download(filePath, fileName);
});
Frontend will send a post request to Scala Play Framework API to download a file. The response header is like :
Access-Control-Allow-Credentials:true
Access-Control-Allow-Origin:http://localhost:8000
Content-Disposition:attachment;
filename="logo_10248191299068944166699.png";
filename*=utf-8'logo_10248191299068944166699.png
Content-Length:53765
Content-Type:image/png
Date:Thu, 07 Sep 2017 13:05:57 GMT
Vary:Origin
My react js code is as below:
const FileDownload = require('react-file-download')
axios(req).then(response => (response.status === 200? response :
null)).then(res =>
{
FileDownload(res.data, filename)
})
It can be downloaded automatically but the file cannot be read. For example, if I download an image, the image cannot be rendered. If I download a zip file, it cannot be extracted. I already tried React-FileDownload, FileSaver, convert the res.data into arraybuffer with the creation of 8 bit array for loop - I.Just.Cant.Make.It.Work.
When I erase the extension format from ubuntu and open it on Atom, these shows up. And from the download tab in Chrome, it stated blob:http://localhost:8000/4de5d808-67a6-4d4e-9920-24bd342664f6
�PNG
IHDRwB���gAMA���asRGB���
cHRMz&�����u0�`:�p��Q<bKGD�������
pHYs.#.#x�?v�IDATx���w�e�Y����9WܹrN]]�-����0�2��,����t|
�=w�{ƹ�&����`LI��`0&I�J��j�����}��J���Pa�=W�~����ݭ��jϵ~�}��1`�|�;��֟zQj�?xz�����z�N-�^n5��$�m�:Uv��Sv�]�N��%=✾s����V��Ǜ?l����>$)��7��p�y{B]]�Ò�T��J:i�̥���+.�V5����$����u����u^�����-��%��tJ��ً�[��8��$}���UOI�{]v��N�3k�I�!�+$}�����I'���cW���_sNF�DҏI�Ip�9��$�`��
I solved the problem. It lies in the POST request.
url: url + '/storage/download_file',
method: 'POST',
responseType: 'blob', //THE KEY TO SUCCESS
headers: {
Authorization: 'Bearer ' + token,
Accept: 'application/json',
'Content-Type': 'application/json'
}
Have to add responseType: 'blob'
I changed to FileSaver to download file.
var blob = new Blob([res.data], {type: "application/octet-stream"});
FileSaver.saveAs(blob, filename)
Solution above is working but I don't like to install excessive packages
Axios
url: '/url
responseType: 'blob'
JS
const link = document.createElement('a');
const url = URL.createObjectURL(blob);
link.href = url;
link.download = fileName;
document.body.appendChild(link); // optional
link.click();
document.body.removeChild(link); // optional