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);
}
I have the following code to let users download data strings in csv file.
exportData = 'data:text/csv;charset=utf-8,';
exportData += 'some csv strings';
encodedUri = encodeURI(exportData);
newWindow = window.open(encodedUri);
It works just fine that if client runs the code it generates blank page and starts downloading the data in csv file.
So I tried to do this with JSON object like
exportData = 'data:text/json;charset=utf-8,';
exportData += escape(JSON.stringify(jsonObject));
encodedUri = encodeURI(exportData);
newWindow = window.open(encodedUri);
But I see only a page with the JSON data displayed on it, not downloading it.
I went through some research and this one claims to work but I don't see any difference to my code.
Am I missing something in my code?
Thanks for reading my question:)
This is how I solved it for my application:
HTML:
<a id="downloadAnchorElem" style="display:none"></a>
JS (pure JS, not jQuery here):
var dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(storageObj));
var dlAnchorElem = document.getElementById('downloadAnchorElem');
dlAnchorElem.setAttribute("href", dataStr );
dlAnchorElem.setAttribute("download", "scene.json");
dlAnchorElem.click();
In this case, storageObj is the js object you want to store, and "scene.json" is just an example name for the resulting file.
This approach has the following advantages over other proposed ones:
No HTML element needs to be clicked
Result will be named as you want it
no jQuery needed
I needed this behavior without explicit clicking since I want to trigger the download automatically at some point from js.
JS solution (no HTML required):
function downloadObjectAsJson(exportObj, exportName){
var dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(exportObj));
var downloadAnchorNode = document.createElement('a');
downloadAnchorNode.setAttribute("href", dataStr);
downloadAnchorNode.setAttribute("download", exportName + ".json");
document.body.appendChild(downloadAnchorNode); // required for firefox
downloadAnchorNode.click();
downloadAnchorNode.remove();
}
Found an answer.
var obj = {a: 123, b: "4 5 6"};
var data = "text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(obj));
$('download JSON').appendTo('#container');
seems to work fine for me.
** All credit goes to #cowboy-ben-alman, who is the author of the code above **
You could try using:
the native JavaScript API's Blob constructor and
the FileSaver.js saveAs() method
No need to deal with any HTML elements at all.
var data = {
key: 'value'
};
var fileName = 'myData.json';
// Create a blob of the data
var fileToSave = new Blob([JSON.stringify(data)], {
type: 'application/json'
});
// Save the file
saveAs(fileToSave, fileName);
If you wanted to pretty print the JSON, per this answer, you could use:
JSON.stringify(data,undefined,2)
This would be a pure JS version (adapted from cowboy's):
var obj = {a: 123, b: "4 5 6"};
var data = "text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(obj));
var a = document.createElement('a');
a.href = 'data:' + data;
a.download = 'data.json';
a.innerHTML = 'download JSON';
var container = document.getElementById('container');
container.appendChild(a);
http://jsfiddle.net/sz76c083/1
ES6+ version for 2021; no 1MB limit either:
This is adapted from #maia's version, updated for modern Javascript with the deprecated initMouseEvent replaced by new MouseEvent() and the code generally improved:
const saveTemplateAsFile = (filename, dataObjToWrite) => {
const blob = new Blob([JSON.stringify(dataObjToWrite)], { type: "text/json" });
const link = document.createElement("a");
link.download = filename;
link.href = window.URL.createObjectURL(blob);
link.dataset.downloadurl = ["text/json", link.download, link.href].join(":");
const evt = new MouseEvent("click", {
view: window,
bubbles: true,
cancelable: true,
});
link.dispatchEvent(evt);
link.remove()
};
If you want to pass an object in:
saveTemplateAsFile("filename.json", myDataObj);
Simple, clean solution for those who only target modern browsers:
function downloadTextFile(text, name) {
const a = document.createElement('a');
const type = name.split(".").pop();
a.href = URL.createObjectURL( new Blob([text], { type:`text/${type === "txt" ? "plain" : type}` }) );
a.download = name;
a.click();
}
downloadTextFile(JSON.stringify(myObj), 'myObj.json');
The following worked for me:
/* function to save JSON to file from browser
* adapted from http://bgrins.github.io/devtools-snippets/#console-save
* #param {Object} data -- json object to save
* #param {String} file -- file name to save to
*/
function saveJSON(data, filename){
if(!data) {
console.error('No data')
return;
}
if(!filename) filename = 'console.json'
if(typeof data === "object"){
data = JSON.stringify(data, undefined, 4)
}
var blob = new Blob([data], {type: 'text/json'}),
e = document.createEvent('MouseEvents'),
a = document.createElement('a')
a.download = filename
a.href = window.URL.createObjectURL(blob)
a.dataset.downloadurl = ['text/json', a.download, a.href].join(':')
e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null)
a.dispatchEvent(e)
}
and then to call it like so
saveJSON(myJsonObject, "saved_data.json");
I recently had to create a button that would download a json file of all values of a large form. I needed this to work with IE/Edge/Chrome. This is what I did:
function download(text, name, type)
{
var file = new Blob([text], {type: type});
var isIE = /*#cc_on!#*/false || !!document.documentMode;
if (isIE)
{
window.navigator.msSaveOrOpenBlob(file, name);
}
else
{
var a = document.createElement('a');
a.href = URL.createObjectURL(file);
a.download = name;
a.click();
}
}
download(jsonData, 'Form_Data_.json','application/json');
There was one issue with filename and extension in edge but at the time of writing this seemed to be a bug with Edge that is due to be fixed.
Hope this helps someone
downloadJsonFile(data, filename: string){
// Creating a blob object from non-blob data using the Blob constructor
const blob = new Blob([JSON.stringify(data)], { type: 'application/json' });
const url = URL.createObjectURL(blob);
// Create a new anchor element
const a = document.createElement('a');
a.href = url;
a.download = filename || 'download';
a.click();
a.remove();
}
You can easily auto download file with using Blob and transfer it in first param downloadJsonFile. filename is name of file you wanna set.
The download property of links is new and not is supported in Internet Explorer (see the compatibility table here). For a cross-browser solution to this problem I would take a look at FileSaver.js
If you prefer console snippet, raser, than filename, you can do this:
window.open(URL.createObjectURL(
new Blob([JSON.stringify(JSON)], {
type: 'application/binary'}
)
))
React: add this where you want in your render method.
• Object in state:
<a
className="pull-right btn btn-primary"
style={{ margin: 10 }}
href={`data:text/json;charset=utf-8,${encodeURIComponent(
JSON.stringify(this.state.objectToDownload)
)}`}
download="data.json"
>
DOWNLOAD DATA AS JSON
</a>
• Object in props:
<a
className="pull-right btn btn-primary"
style={{ margin: 10 }}
href={`data:text/json;charset=utf-8,${encodeURIComponent(
JSON.stringify(this.props.objectToDownload)
)}`}
download="data.json"
>
DOWNLOAD DATA AS JSON
</a>
className and style are optional, modify the style according to your needs.
Try to set another MIME-type:
exportData = 'data:application/octet-stream;charset=utf-8,';
But there are can be problems with file name in save dialog.
const exportToJson = (data: {}) =>{
const link = document.createElement("a");
link.href =
data:text/json;charset=utf8,${encodeURIComponent(JSON.stringify(data))}; link.download = 'example.json'; link.click(); }
Make sure to clean up the the created link after if you don't want a random element that does nothing.
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
In React, I uploaded a file using:
let reader = new FileReader();
reader.readAsDataURL(file);
reader.onloadend = function() {
let base64data = reader.result;
uploadFile(base64data);
return;
}
This gives me a Base64 encoded text data:application/octet-stream;base64,JVBERi0xLj...
This is fine as when I decode 'JVBERi0xLj...' I get the correct text in case of a text file.
When a download request is made to the server I get the same data back but I'm having a difficulty downloading the file. I receive the same base64 encoded string in the response from the server but unable to open the downloaded file.
I have done the following:
const blob = new Blob([fetchData], { type: 'application/pdf' })
let url = window.URL.createObjectURL(blob);
let a = document.createElement('a');
a.href = blob;
a.download = 'doc.pdf';
a.click();
Any ideas?
Note: The upload file is converted to base64 to avoid any http communication issues.
Solution following your suggestions:
let fetchDataModified = `data:application/pdf;base64,${fetchData }`;
let a = document.createElement("a");
a.href = fetchData;
a.download = 'doc.pdf';
a.click();
When converting to Base64 during upload the data type was set to 'application/octet-stream'. However, when downloading I changed that to 'application/pdf' following Vaibhav's suggestion and used createElement instead of createObjectURL and it worked. Thank you
“data:application/pdf” + the base64 string that you saved into our database
I have a binary data saved in MongoDB. How can I covert this binary data into downloadable file of any filetype(.txt,.pdf,.img).
Using JavaScript blob I tried to generate and download the file as per below code snippet;
const a = document.createElement('a');
document.body.appendChild(a);
a.style.display = 'none';
const data = =attachments[0].file.data;
const blob = new Blob([data], {type: "octet/stream"});
const url = window.URL.createObjectURL(blob);
a.href = url;
a.download = name;
a.click();
window.URL.revokeObjectURL(url);
This doesn't seem to work as it downloads a file with no extension and as [object Object] if I open the file through Notepad. What data should be set as first parameter in the new Blob(data, type) to get the correct file