I try to create a button that would download a csv file. I have to make the file using windows-1251 charset.
But no matter what I do the file ended up in utf-8. Right now I'm trying something like:
async createCsv(result) {
const arrData = result.data
const aliases = result.aliases
let csvContent = [
Object.keys(arrData[0]).map(item => aliases[item]).join(";"),
...arrData.map(item => Object.values(item).join(";"))
]
.join("\n")
.replace(/(^\[)|(\]$)/gm, "");
const data = new Blob([csvContent], {
type: "text/csv;charset=windows-1251;"
});
const link = document.createElement("a");
link.setAttribute("href", URL.createObjectURL(data));
link.setAttribute("download", (new Date).toLocaleString() + ".csv");
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
And the file is in utf-8.
Is there a way to change the charset?
looking for the same last day.
that's the answer that really works
blob with conversion to 8bit cp1251 or cp1252
in my project ends up with the following
import * as iconv from 'iconv-lite'
let outdata = this.bankf.getOutputFile();
const encoded = iconv.encode (outdata,'win1251');
var file = new Blob ([encoded], {type: 'text/plain;charset=windows-1251'});
var link = document.createElement("a");
var url = URL.createObjectURL(file);
link.setAttribute("href", url);
link.setAttribute("download", "filename.txt");
document.body.appendChild(link);
link.click();
setTimeout(function() {document.body.removeChild(link); window.URL.revokeObjectURL(url); }, 0);
still looking for other solution as iconv brings around 400kb code , but for now. at least it works
Related
This is what I get by Flask:
#app.route('/api/downloads/', methods=['POST'])
def download_file():
uploads = app.config['UPLOAD_FOLDER']
try:
response = request.get_json()
filename = response["filename"]
return send_from_directory(directory=uploads, path=filename, as_attachment=True)
except Exception as e:
print(e)
return {}, 404
This is my JavaScript, I got this snippet from here:
function downloadStuff (data) {
const link = document.createElement('a');
var binaryData = [];
binaryData.push(data);
const url = window.URL.createObjectURL(new Blob(binaryData, {type: "application/zip"})) <- ?
link.href = url;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
On const url = window.URL.createObjectURL(new Blob(binaryData, {type: "application/zip"})) I define the type, like here: "zip".
How can I be independent on the file type specification since I want to be able to download different file types and not only "zip"?
Try this, pass second argument as a type and use it in your function like this. (Note: make zip bydefault if you don't pass any type it takes zip)
function downloadStuff (data, type = 'zip') {
const link = document.createElement('a');
var binaryData = [];
binaryData.push(data);
const url = window.URL.createObjectURL(new Blob(binaryData,
{type:`application/${type}`})) <- ?
link.href = url;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
When I try to save on Angular a base64 file with this format :
// receivedFile.file = "data:image/jpeg;base64,/9j/4AAQSkZJR..."
var a = document.createElement('a');
const blob = new Blob([receivedFile.file], {type: receivedFile.infos.type});
a.href = URL.createObjectURL(blob);
a.download = receivedFile.infos.name;
a.click();
This code give me a corrupted file, how can I do ?
In Angular (and in general) I use file-saver :
import { saveAs } from 'file-saver';
const blob = new Blob([receivedFile], {type: receivedFile.infos.type});
FileSaver.saveAs(blob, receivedFile.infos.name);
Also, try to remove the data:image/jpeg;base64, part of the string :
receivedFile.file.replace("data:image/jpeg;base64," , "")
Here is the code which converts base64 to downloadable file format in angular.
If for example your file type is csv, then below is the code snippet
downloadFile(base64:any,fileName:any){
const src = `data:text/csv;base64,${base64}`;
const link = document.createElement("a")
link.href = src
link.download = fileName
link.click()
link.remove()
}
//calling above function with some sample base64 data
downloadFile("c21hbGxlcg==","demo.csv")
Note: The file type can be anything you can give based on the need(In src of above code snippet).Here I am considering the csv file as example.
So by calling this above function You can download the resultant file will be downloaded from browser.
To resolve this problem :
Removed data:image/jpeg;base64 from the receivedFile.file.
Use the function atob(), const byteCharacters = atob(receivedFile.file);
Then make the blob
const blob = new Blob([byteCharacters], {type: this.receivedFile.infos.type});
try this
const downloadLink = document.createElement('a');
const fileName = 'sample.pdf';
downloadLink.href = linkSource;
downloadLink.download = fileName;
downloadLink.click();
I have a link /api/ticket/1/download to my server and if I copy paste it into the browser, it will start a download of my file with it's filename extension and everything set up already.
How can I do it in javascript? With thymeleaf i was just using <a href="myLink"> and it worked like if I paste it in the browser. But due to react-router a href just goes to another page.
But if I use await fetch like this:
let url1 = '/api/ticket/' + fileId + '/download';
const response = await fetch(url1);
const blob = response.blob();
const url = window.URL.createObjectURL(new Blob([blob]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', `file.jpg`);
document.body.appendChild(link);
link.click();
i can transfer response into blob, but then i miss the files name and extension.
The only way to solve this that i found is: send file name and extension in a response header and than parse them manualy.
like:
in spring:
myControllerMethod( HttpServletResponse response){
...
response.setContentType(att.getType());
response.setHeader("Content-Disposition", "attachment; filename=\"" + myFileName + "\"");
}
in react:
const headers = response.headers;
const file = headers.get("Content-Disposition");
and then parse manully this 'file' to get filenamel;
Try in this way, it may help you :
fetch('http://localhost:8080/employees/download')
.then(response => {
response.blob().then(blob => {
let url = window.URL.createObjectURL(blob);
let a = document.createElement('a');
a.href = url;
a.download = 'employees.json';
a.click();
});
For more reference you can go through This link
I got an Api which return File, i write response into this.getPDFBuffer, here you can see it.
Main problem is that if I use my function it downloads an empty file, but if i use Postman to perform an request it saves correctly
//this.getPDFBuffer contains response.data:
var file = new Blob([this.getPDFBuffer], {type: 'application/pdf'});
var url = window.URL.createObjectURL(file);
var link = document.createElement('a');
link.setAttribute('href', url);
link.setAttribute('download','download');
link.click();
I expect download a file
This is not a full answer but:
On line 4 and line 5, I suggest using a link.href = url; instead of setAttribute(). For line 5, it is link.download = "download";. This could fix the problem, but this is not meant to be a fix, just a tip.
You also have to document.body.appendChild(link) probably after line 5 so it gets displayed in the HTML.
Also, on line 5, you might have to set different parameters(see https://www.w3schools.com/TAGS/att_a_download.asp).
Changed code:
var file = new Blob([this.getPDFBuffer], {type: 'application/pdf'});
var url = window.URL.createObjectURL(file);
var link = document.createElement('a');
link.href = url;
link.download = "download"; // Maybe 'link.download;'
document.body.appendChild(link)
link.click();
I have a web service that returns PDF file content in its response. I want to download this as a pdf file when user clicks the link. The javascript code that I have written in UI is as follows:
$http.get('http://MyPdfFileAPIstreamURl').then(function(response){
var blob=new File([response],'myBill.pdf',{type: "text/pdf"});
var link=document.createElement('a');
link.href=window.URL.createObjectURL(blob);
link.download="myBill.pdf";
link.click();
});
'response' contains the PDF byte array from servlet outputstream of 'MyPdfFileAPIstreamURl'. And also the stream is not encrypted.
So when I click the link, a PDF file gets downloaded successfully of size around 200KB. But when I open this file, it opens up with blank pages. The starting content of the downloaded pdf file is in the image.
I can't understand what is wrong here. Help !
This is the downloaded pdf file starting contents:
solved it via XMLHttpRequest and xhr.responseType = 'arraybuffer';
code:
var xhr = new XMLHttpRequest();
xhr.open('GET', './api/exportdoc/report_'+id, true);
xhr.responseType = 'arraybuffer';
xhr.onload = function(e) {
if (this.status == 200) {
var blob=new Blob([this.response], {type:"application/pdf"});
var link=document.createElement('a');
link.href=window.URL.createObjectURL(blob);
link.download="Report_"+new Date()+".pdf";
link.click();
}
};
xhr.send();
i fetched the data from server as string(which is base64 encoded to string) and then on client side i decoded it to base64 and then to array buffer.
Sample code
function solution1(base64Data) {
var arrBuffer = base64ToArrayBuffer(base64Data);
// It is necessary to create a new blob object with mime-type explicitly set
// otherwise only Chrome works like it should
var newBlob = new Blob([arrBuffer], { type: "application/pdf" });
// IE doesn't allow using a blob object directly as link href
// instead it is necessary to use msSaveOrOpenBlob
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(newBlob);
return;
}
// For other browsers:
// Create a link pointing to the ObjectURL containing the blob.
var data = window.URL.createObjectURL(newBlob);
var link = document.createElement('a');
document.body.appendChild(link); //required in FF, optional for Chrome
link.href = data;
link.download = "file.pdf";
link.click();
window.URL.revokeObjectURL(data);
link.remove();
}
function base64ToArrayBuffer(data) {
var binaryString = window.atob(data);
var binaryLen = binaryString.length;
var bytes = new Uint8Array(binaryLen);
for (var i = 0; i < binaryLen; i++) {
var ascii = binaryString.charCodeAt(i);
bytes[i] = ascii;
}
return bytes;
};
I was facing the same problem in my React project.
On the API I was using res.download() of express to attach the PDF file in the response. By doing that, I was receiving a string based file. That was the real reason why the file was opening blank or corrupted.
In my case the solution was to force the responseType to 'blob'. Since I was making the request via axios, I just simply added this attr in the option object:
axios.get('your_api_url_here', { responseType: 'blob' })
After, to make the download happen, you can do something like this in your 'fetchFile' method:
const response = await youtServiceHere.fetchFile(id)
const pdfBlob = new Blob([response.data], { type: "application/pdf" })
const blobUrl = window.URL.createObjectURL(pdfBlob)
const link = document.createElement('a')
link.href = blobUrl
link.setAttribute('download', customNameIfYouWantHere)
link.click();
link.remove();
URL.revokeObjectURL(blobUrl);
solved it thanks to rom5jp but adding the sample code for golang and nextjs
in golang using with gingonic context
c.Header("Content-Description", "File-Transfer")
c.Header("Content-Transfer-Encoding", "binary")
c.Header("Content-Disposition","attachment; filename="+fileName)
c.Header("Content-Type", "application/pdf; charset=utf-8")
c.File(targetPath)
//c.FileAttachment(targetPath,fileName)
os.RemoveAll(targetPath)
in next js
const convertToPDF = (res) => {
const uuid = generateUUID();
var a = document.createElement('a');
var url = window.URL.createObjectURL(new Blob([res],{type: "application/pdf"}));
a.href = url;
a.download = 'report.pdf';
a.click();
window.URL.revokeObjectURL(url);
}
const convertFile = async() => {
axios.post('http://localhost:80/fileconverter/upload', {
"token_id" : cookies.access_token,
"request_type" : 1,
"url" : url
},{
responseType: 'blob'
}).then((res)=>{
convertToPDF(res.data)
}, (err) => {
console.log(err)
})
}
I was able to get this working with fetch using response.blob()
fetch(url)
.then((response) => response.blob())
.then((response) => {
const blob = new Blob([response], {type: 'application/pdf'});
const link = document.createElement('a');
link.download = 'some.pdf';
link.href = URL.createObjectURL(blob);
link.click();
});
Changing the request from POST to GET fixed it for me