My web application lets the users "save" a file by downloading it as described below (Source).
However browsers like Firefox in its default setting then tries to open the file and says "Opening filename.json" and not "Saving File". While I understand the reason for this is that the browser tries to immediately open a downloaded file if configured as such, this confuses my users because there are now three different words ("download", "save", "open") for the same operation and they don't know if they chose the wrong one. There is also a load option where users can upload their saved data to load it in the application, adding to the confusion.
Is there any way to tell the browser to stop trying to open the file (which it cannot do anyways, it is a custom format for that web application), or is there any other way to provide more clarity to the users?
export function saveJson(data,fileName)
{
if(a===null)
{
a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
}
const json = JSON.stringify(data);
const blob = new Blob([json], {type: "application/json"});
const url = window.URL.createObjectURL(blob);
a.href = url;
a.download = fileName;
a.click();
window.URL.revokeObjectURL(url);
log.debug("JSON File saved: "+fileName);
}
Related
I've written a NodeJS/Express application that generates and downloads an excel document (created using ExcelJS) upon the user pressing a button. When the user presses the button, the file is generated then downloaded to the user's default download location. I'd prefer the user be able to select where they'd like to download the file upon pressing the button. Is this possible?
My current JavaScript code is as follows:
export_button.onclick = async function() {
await fetch('/download', {
method: 'POST'
})
.then(resp => resp.blob())
.then(blob => {
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = 'document.xlsx';
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
});
}
This is possible in desktop versions of latest Chrome-based browsers (Chrome, Edge, Opera).
Current support:
https://caniuse.com/mdn-api_window_showsavefilepicker
https://wicg.github.io/file-system-access/#api-showsavefilepicker
https://wicg.github.io/file-system-access/#enumdef-wellknowndirectory
We use this for working with PDF files: https://webpdf.pro/doc/ (draft for next release).
Note that you can suggest a file name and folder, customize the file type list, offer multiple types!
In fact, we have a method called exactly that: <pdf-file>.saveAs().
Online version of Visual Studio Code is another recent user: https://vscode.dev/.
Apple and Firefox are likely to drag their feet on this one citing privacy/security concerns for at least the next few months though.
async function saveFile(){
var mystring = "Hello World!";
var myblob = new Blob([mystring], {
type: 'text/plain'
});
if( window.showSaveFilePicker ) {
const opts = {
types: [{
description: 'MYfile',
accept: {'text/plain': ['.txt']},
}],
suggestedName: 'myFileText',
};
var handle = await showSaveFilePicker(opts);
var writable = await handle.createWritable();
await writable.write( myblob );
writable.close();
}else{
alert( "xxx" );
}
}
<button id="botonx" onClick="saveFile()" >Save File</button>
I don't believe this is possible, no. This behaviour is controlled by settings in the user's browser. For most browsers, or perhaps even all of them, the default behaviour is to always download files to a default location without showing a prompt where the user can change its destination or filename. Understandably, you can't change a user's browser settings from JavaScript.
Glad to see I was wrong about this, I didn't realise the File System Access API Cetin Sert's answer describes exists.
I am trying to create a button that triggers a download of a JSON file. (And please i don't want to use any libraries to achieve this). Thank you.
import Data from '../Data';
let data = Data;
<Button>Download</Button>
Triggering browser download from front-end is not reliable.
What you should do is, create an endpoint that when called, will provide the correct response headers, thus triggering the browser download.
Front-end code can only do so much. The 'download' attribute for example, might just open the file in a new tab depending on the browser.
Take a look at this solution: How to create a file in memory for user to download, but not through server? I have rewritten their code a bit, but basically for your case, you'd want...
// Set globals
var mimetype = 'application/json';
var filename = 'yourfile.json';
// Create Dummy A Element
var a = window.document.createElement('a');
// createObjectURL for local data as a Blob type
a.href = window.URL.createObjectURL(new Blob([data], {
encoding: "UTF-8",
type: mimetype + ";charset=UTF-8",
}));
a.download = filename;
// Download file and remove dummy element
document.body.appendChild(a);
a.click();
a.remove();
You would need to create a file using your data and then create a downloadable link
and append it in whichever part of your application you would like to.
const fileName = "file";
const json = JSON.stringify(data);
const blob = new Blob([json],{type:'application/json'});
const href = await URL.createObjectURL(blob); // Create a downloadable link
const link = document.createElement('a');
link.href = href;
link.download = fileName + ".json";
document.body.appendChild(link); // This can any part of your website
link.click();
document.body.removeChild(link);
I have an app that converts files. I'm sending a file, and the converted file is being returned in the form of a data URL. Had everything working great in Chrome, but IE (10/11/Edge) is a different story. Have tried several things to no prevail:
1) HTML5 download attribute is not supported in IE. I tried assigning the returned URL as an anchor tag href, but invoking .click() is not supported, and manually clicking on the link does nothing.
2) window.navigator.msSaveOrOpenBlob() and File Saver.js. The SaveAs dialog pops up, but the blob is empty and never downloads anything.
var file= new Blob([returnedFile], {type: "application/pdf"});
window.navigator.msSaveOrOpenBlob(file, 'doc.pdf');
FileSaver.saveAs(file, 'doc.pdf');
Any ideas or suggestions to try?
First, try to verify saveAs existance:
if (window.saveAs) {
window.saveAs(blob, name);
} else {
navigator.saveBlob(blob, name);
}
As for the Blob itself:
create <a>
update href:
a.href = window.URL.createObjectURL(new Blob(returnedFile, {type: "application/pdf"}));
fire click event
More or less the same functionality can be reviewed there: http://jsfiddle.net/VB59f/2/
Ended up getting the browser via navigator.userAgent.match and handling the save based on each browser accordingly:
var saveData = (data, fileName) => {
IE:
FileSaver.saveAs(blob, fileName + "." + extension);
Chrome:
var downloadLink = document.createElement("a");
document.body.appendChild(downloadLink);
downloadLink.style.display = "none";
downloadLink.href = data;
downloadLink.download = fileName;
downloadLink.click();
I have a web application for downloading files. Everything works fine except when I want to download a file more than 1GB .
This is my java code:
InputStream in = new FileInputStream(new File(folderFile.getAbsolutePath()));
org.apache.commons.io.IOUtils.copy(in, response.getOutputStream());
response.flushBuffer();
in.close();
HTTP request :
$http({
method:'get',
url:this.apiDownloadFileUrl,
responseType:'arraybuffer',
cache: false
});
and here is client side: I got data successfully on client, but when I make it Blob , if the data size was more than 500MB , nothing happened and it wasn't downloaded. Also, I can download 300MB ...
How can I check if it is a memory problem, or a server problem? ... When I download from gmail , I can download more than 1GB .
.success(function(databack) {
var file = new Blob([ databack ], {
type : 'application/csv'
});
var fileURL = window.URL.createObjectURL(file);
var a = document.createElement('a');
a.href = fileURL;
a.target = '_blank';
a.download = data;
document.body.appendChild(a);
a.click();
Have you tried using the copyLarge() methods from IOUtils? For the copy() methods the JavaDoc says:
"For large streams use the copyLarge(InputStream, OutputStream) method."
You should check the response message first, and decide which side fire the problem.
As my experience, you should check whether the file was cached by the browser rather than any problems~
I'm trying to save a SVG from a canvas as PNG file using javascript.
The below code seems to work fine on Chrome and Firefox, but in IE 10 i get the below error in my console.
SCRIPT5: Access is denied.
FInd below the code that I've used:
var image = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
var a = $('<a>').attr("href", canvas.toDataURL("image/png")).attr("download", title + "png").appendTo($('#VisitsContainer'));
a[0].click();
a.remove();
The console points to the click event that I'm trying to invoke.
The download attribute is not implemented in Internet Explorer.
http://caniuse.com/download
For Internet explorer you can use the "SaveAs" command.
A note about security:
Browsers serve 2 masters.
Browsers must serve the user's request to save content to their local drive.
Browsers must also restrict potentially malicious code from automatically downloading bits onto the users local drive.
To reconcile the 2 tasks, browsers take the approach that users can download content to their local drive after some confirming process (like a Save button).
Using a[0].click(); to confirm for the user runs contrary to the browser's attempt to provide security.
FileSave.js is a cross-browser library that will save your canvas to the users local drive. It conforms to security issues by requiring the user to click a button to OK the download.
https://github.com/eligrey/FileSaver.js/
Necromancing.
On IE, you don't need to create a link.
It's sufficient to create a new Blob.
function saveMe(data, fileName)
{
var json = JSON.stringify(data),
blob = new Blob([json], { type: "octet/stream" }),
url = window.URL.createObjectURL(blob);
if (navigator.msSaveOrOpenBlob)
{
navigator.msSaveOrOpenBlob(blob, fileName);
return;
}
else if (window.navigator.msSaveBlob)
{ // for IE browser
window.navigator.msSaveBlob(blob, fileName);
return;
}
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
a.href = url;
a.download = fileName;
a.click();
window.URL.revokeObjectURL(url);
}
var data = { x: 42, s: "hello, world", d: new Date() }, fileName = "my-download.json";
// saveData(data, fileName);
saveMe(data, fileName);