How to save a png from javascript variable - javascript

I have an image encoded in base64 in a javascript variable : data:image/png;base64, base64 data
[EDIT]
I need to save that file to disk without asking to the visitor to do a right click
[/EDIT]
Is it possible ? How ?
Thanks in advance
Best regards

I know this question is 2 years old, but hopefully people will see this update.
You can prompt the user to save an image in a base64 string (and also set the filename), without asking the user to do a right click
var download = document.createElement('a');
download.href = dataURI;
download.download = filename;
download.click();
Example:
var download = document.createElement('a');
download.href = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==';
download.download = 'reddot.png';
download.click();
In order to trigger a click event using Firefox, you need to do what it is explained in this SO answer. Basically:
function fireEvent(obj,evt){
var fireOnThis = obj;
if(document.createEvent ) {
var evObj = document.createEvent('MouseEvents');
evObj.initEvent( evt, true, false );
fireOnThis.dispatchEvent( evObj );
} else if( document.createEventObject ) {
var evObj = document.createEventObject();
fireOnThis.fireEvent( 'on' + evt, evObj );
}
}
fireEvent(download, 'click')
As of 20/03/2013, the only browser that fully supports the download attribute is Chrome. Check the compatibility table here

... without asking to the visitor anyhing ... Is it possible?
No, that would have been a security hole. If it was possible, one would be able to write malware to the enduser's disk unaskingly. Your best bet may be a (signed) Java Applet. True, it costs a bit of $$$ to get it signed (so that it doesn't pop security warnings), but it is able to write data to enduser's disk without its permission.

I am surprised nobody here mentioned using HTML5 blobs together with a couple of nice libraries.
You first need https://github.com/eligrey/FileSaver.js/ and https://github.com/blueimp/JavaScript-Canvas-to-Blob.
Then you can load the image into a canvas
base_image = new Image();
base_image.src ='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==';
the canvas into a blob
var canvas = document.getElementById('YourCanvas');
context = canvas.getContext('2d');
// Draw image within
context.drawImage(base_image, 0,0);
and finally save it
x_canvas.toBlob(function(blob) {
saveAs(blob, "screenshot.png");
}, "image/png");
FF is not fully supported but at least you get a separate page with the image.
Check this out: http://jsfiddle.net/khhmm/9/
EDIT: this is not compatible with Safari / Mac.

As other answers already stated, you cannot do it only with javascript. If you want, you can send the data (using normal HTTP POST) to a PHP script, call header('Content-type: image/png') and output the decoded image data to the page using echo base64_decode($base64data).
This will work just as if user clicked on an image and open it or prompt him to save the file to disk (the normal browser's save file dialog).

It's not possible.
If it was, browsers would be massively insecure, being able to write random data to your hard disk without user interaction.

with javascript, you can't. the only real possibility i can think of will be a java-applet, but maybe (i don't know how long that image should be saved) you could simply add an img-tag with you png and force caching (but if the user deletes his cache, the image will be gone).

I think it's possible with JavaScript if you use ActiveX.
Another possibility is to make the server spit out that file with a different mime type so the browser asks the user to save it.

I think you can do it something(maybe not only with javascript...xul programming needed). There are Firefox addons that save images to a folder(check Firefox addons site)

You can make this file as blob on the server and use setTimeout function in order to fire the download.

The accepted solution seems to have a limitation for large data. If you're running into this (instead of the downloaded file's name, I see "download" and "Failed - Network error" in Chrome), here's what I did in order to download a 2mb file:
const blob = await (await fetch(document.getElementById('canvasID').toDataURL())).blob();
const file = new File([blob], {type:"image/png", lastModified: new Date()});
var a = document.createElement('a');
a.href = window.URL.createObjectURL(file);
a.download = 'image.png';
a.click();

Related

JavaScript: How to create and save text file [duplicate]

This question already has answers here:
How to create a file in memory for user to download, but not through server?
(22 answers)
Closed 2 years ago.
I have data that I want to write to a file, and open a file dialog for the user to choose where to save the file. It would be great if it worked in all browsers, but it has to work in Chrome. I want to do this all client-side.
Basically I want to know what to put in this function:
saveFile: function(data)
{
}
Where the function takes in data, has the user select a location to save the file, and creates a file in that location with that data.
Using HTML is fine too, if that helps.
A very minor improvement of the code by Awesomeness01 (no need for anchor tag) with addition as suggested by trueimage (support for IE):
// Function to download data to a file
function download(data, filename, type) {
var file = new Blob([data], {type: type});
if (window.navigator.msSaveOrOpenBlob) // IE10+
window.navigator.msSaveOrOpenBlob(file, filename);
else { // Others
var a = document.createElement("a"),
url = URL.createObjectURL(file);
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
setTimeout(function() {
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}, 0);
}
}
Tested to be working properly in Chrome, FireFox and IE10.
In Safari, the data gets opened in a new tab and one would have to manually save this file.
function download(text, name, type) {
var a = document.getElementById("a");
var file = new Blob([text], {type: type});
a.href = URL.createObjectURL(file);
a.download = name;
}
click here to download your file
<button onclick="download('file text', 'myfilename.txt', 'text/plain')">Create file</button>
And you would then download the file by putting the download attribute on the anchor tag.
The reason I like this better than creating a data url is that you don't have to make a big long url, you can just generate a temporary url.
This project on github looks promising:
https://github.com/eligrey/FileSaver.js
FileSaver.js implements the W3C saveAs() FileSaver interface in
browsers that do not natively support it.
Also have a look at the demo here:
http://eligrey.com/demos/FileSaver.js/
Choosing the location to save the file before creating it is not possible. But it is possible, at least in Chrome, to generate files using just JavaScript. Here is an old example of mine of creating a CSV file. The user will be prompted to download it. This, unfortunately, does not work well in other browsers, especially IE.
<!DOCTYPE html>
<html>
<head>
<title>JS CSV</title>
</head>
<body>
<button id="b">export to CSV</button>
<script type="text/javascript">
function exportToCsv() {
var myCsv = "Col1,Col2,Col3\nval1,val2,val3";
window.open('data:text/csv;charset=utf-8,' + escape(myCsv));
}
var button = document.getElementById('b');
button.addEventListener('click', exportToCsv);
</script>
</body>
</html>
For latest browser, like Chrome, you can use the File API as in this tutorial:
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
window.requestFileSystem(window.PERSISTENT, 5*1024*1024 /*5MB*/, saveFile, errorHandler);
function SaveBlobAs(blob, file_name) {
if (typeof navigator.msSaveBlob == "function")
return navigator.msSaveBlob(blob, file_name);
var saver = document.createElementNS("http://www.w3.org/1999/xhtml", "a");
var blobURL = saver.href = URL.createObjectURL(blob),
body = document.body;
saver.download = file_name;
body.appendChild(saver);
saver.dispatchEvent(new MouseEvent("click"));
body.removeChild(saver);
URL.revokeObjectURL(blobURL);
}
Tried this in the console, and it works.
var aFileParts = ['<a id="a"><b id="b">hey!</b></a>'];
var oMyBlob = new Blob(aFileParts, {type : 'text/html'}); // the blob
window.open(URL.createObjectURL(oMyBlob));
You cannot do this purely in Javascript. Javascript running on browsers does not have enough permission yet (there have been proposals) due to security reasons.
Instead, I would recommend using Downloadify:
A tiny javascript + Flash library that enables the creation and download of text files without server interaction.
You can see a simple demo here where you supply the content and can test out saving/cancelling/error handling functionality.
For Chrome and Firefox, I have been using a purely JavaScript method.
(My application cannot make use of a package such as Blob.js because it is served from a special engine: a DSP with a WWWeb server crammed in and little room for anything at all.)
function FileSave(sourceText, fileIdentity) {
var workElement = document.createElement("a");
if ('download' in workElement) {
workElement.href = "data:" + 'text/plain' + "charset=utf-8," + escape(sourceText);
workElement.setAttribute("download", fileIdentity);
document.body.appendChild(workElement);
var eventMouse = document.createEvent("MouseEvents");
eventMouse.initMouseEvent("click", true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
workElement.dispatchEvent(eventMouse);
document.body.removeChild(workElement);
} else throw 'File saving not supported for this browser';
}
Notes, caveats, and weasel-words:
I have had success with this code in both Chrome and Firefox clients running in Linux (Maipo) and Windows (7 and 10) environments.
However, if sourceText is larger than a MB, Chrome sometimes (only sometimes) gets stuck in its own download without any failure indication; Firefox, so far, has not exhibited this behavior. The cause might be some blob limitation in Chrome. Frankly, I just don't know; if anybody has any ideas how to correct (or at least detect), please post. If the download anomaly occurs, when the Chrome browser is closed, it generates a diagnostic such as
This code is not compatible with Edge or Internet Explorer; I have not tried Opera or Safari.
StreamSaver is an alternative to save very large files without having to keep all data in the memory.In fact it emulates everything the server dose when saving a file but all client side with service worker.
You can either get the writer and manually write Uint8Array's to it or pipe a binary readableStream to the writable stream
There is a few example showcasing:
How to save multiple files as a zip
piping a readableStream from eg Response or blob.stream() to StreamSaver
manually writing to the writable stream as you type something
or recoding a video/audio
Here is an example in it's simplest form:
const fileStream = streamSaver.createWriteStream('filename.txt')
new Response('StreamSaver is awesome').body
.pipeTo(fileStream)
.then(success, error)
If you want to save a blob you would just convert that to a readableStream
new Response(blob).body.pipeTo(...) // response hack
blob.stream().pipeTo(...) // feature reference
Javascript has a FileSystem API. If you can deal with having the feature only work in Chrome, a good starting point would be: http://www.html5rocks.com/en/tutorials/file/filesystem/.

Saving Webpage With Javascript/jQuery Changes

I was curious if there is a way for users to save a complete webpage after changes have been made via Javascript/jQuery. To my understanding this is only possible with server side coding - but I was unable to find a definitive answer.
As a simple example, I would allow users the ability to customize something like the background color and text of a webpage, and then save their changes to their local machine.
Edit: The resources I'm looking to create will need to be saved to their local machine as a webpage - therefore storing information in the browser is not ideal.
The resources will be used for a program called OBS, where the user will basically be importing the saved elements via the locally saved file.
On modern Browsers, you can use an XMLSerializer and Blob to achieve it :
document.querySelector('input').onchange = function() {
document.body.style.backgroundColor = this.value;
}
document.querySelector('button').onclick = function() {
var a = document.createElement('a');
// serialize the whole document as a string
var doc = new XMLSerializer().serializeToString(document.documentElement);
// convert this string to a blob object
if (window.Blob) {
var blob = new Blob([doc], {type: 'text/html'});
// create a blob URL
a.href = URL.createObjectURL(blob);
} else
//browser don't support Blob object, create a data url
a.href = 'data: text/html; charset=utf8, ' + doc;
/* The following won't work in the snippet but can be used on your server for browsers supporting download attribute
if ('download' in a) {
a.download = 'yourPageName.html';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
} else {*/
a.innerHTML = 'Right click - Save As.. to download the page';
document.body.appendChild(a);
// }
}
Hello
<input placeholder="choose a background color" />
<button>save</button>
It's better to store those settings server side associated with the user itself, so the settings are saved and can be seen in different browsers/ devices, and won't get deleted clearing browser storage.
Anyways, as it's already stated it can be done using the browser local storage
You can use Cookies, sessionStorage or localStorage.
Cookies and localStorage can persist through different sessions, sessionStorage only persists until the browser is closed. From the MDN Web Storage API
sessionStorage maintains a separate storage area for each given origin that's available for the duration of the page session (as long as the browser is open, including page reloads and restores)
localStorage does the same thing, but persists even when the browser is closed and reopened.

Creating download prompt using purely javascript

I have some text data (say var a = 'Hello World From Javascript';)in javascript variable in current window. I want to do the following
through javascript-
1. open a new window and write the text data to the window.
2. set the content type to text/plain.
3. set the content-disposition to attachment, so that download prompt comes.
4. user downloads the text data as a text file and saves it to his local disk.
is this all possible through javascript?
I know we can make ajax calls to server or redirect but in this case instead of following above steps. But in this case, these workarounds are not adaptable.
you can do that using JS & HTML5 features. Please find below a sample code.
var fileParts = ['Hello World From Javascript'];
// Create a blob object.
var bb = new Blob(fileParts,{type : 'text/plain'});
// Create a blob url for this.
var dnlnk = window.URL.createObjectURL(bb);
var currentLnk = $('#blobFl').attr('href');
// blobFl is the id of the anchor tag through which the download will be triggered.
$('#blobFl').attr('href',dnlnk);
$('#blobFl').attr('download','helloworld.txt');
// For some reason trigger from jquery dint work for me.
document.getElementById('blobFl').click();
Triggering a file download without any server request
Unfortunately this is not something you can do with normal browser capabilities. Something like flash or a browser-specific plugin will get you what you need, but security limitations within javascript will not let you download arbitrary data created within the browser.
Also the 'data' url is not supported across all browser/version combinations. I am not sure if your users are constrained on what browser they are using or not but that may limit what you can do with that solution.
Source: Triggering a file download without any server request
If you already have the file on the server (I make an ajax call to generate and save a PDF on the server) - you can do this
window.location.replace(fileUrl);
No, Content-Disposition is a response header, it has to come from the server. I think you could do it with Flash but I wouldn't recommend it.
Here's a clean, pure js version of #Rajagopalan Srinivasan's answer:
var fileParts = ["Hello World From Javascript"];
// The anchor tag to use.
const blobLink = document.getElementById("blobLink");
// Create a blob object.
var blob = new Blob(fileParts, { type: "text/plain" });
// Create a blob url for this.
var blobUrl = window.URL.createObjectURL(blob);
blobLink.setAttribute("href", blobUrl);
blobLink.setAttribute("download", "helloworld.txt");
blobLink.click();
<a id="blobLink">Download</a>

How to create a dynamic file + link for download in Javascript? [duplicate]

This question already has answers here:
How to create a file in memory for user to download, but not through server?
(22 answers)
Closed 6 years ago.
Typically, HTML pages can have link to documents (PDF, etc...) which can be downloaded from the server.
Assuming a Javascript enabled webpage, is it possible to dynamically create a text document (for example) from within the user browser and add a link to download this document without a round trip to the server (or a minimal one)?
In other word, the user would click on a button, the javascript would generate randoms numbers (for example), and put them in a structure. Then, the javascript (JQuery for example) would add a link to the page to download the result as a text file from the structure.
This objective is to keep all (or at least most) of the workload on the user side.
Is this feasible, if yes how?
Here's a solution I've created, that allows you to create and download a file in a single click:
<html>
<body>
<button onclick='download_file("my_file.txt", dynamic_text())'>Download</button>
<script>
function dynamic_text() {
return "create your dynamic text here";
}
function download_file(name, contents, mime_type) {
mime_type = mime_type || "text/plain";
var blob = new Blob([contents], {type: mime_type});
var dlink = document.createElement('a');
dlink.download = name;
dlink.href = window.URL.createObjectURL(blob);
dlink.onclick = function(e) {
// revokeObjectURL needs a delay to work properly
var that = this;
setTimeout(function() {
window.URL.revokeObjectURL(that.href);
}, 1500);
};
dlink.click();
dlink.remove();
}
</script>
</body>
</html>
I created this by adapting the code from this HTML5 demo and messing around with things until it worked, so I'm sure there are problems with it (please comment or edit if you have improvements!) but it's a working, single-click solution.
(at least, it works for me on the latest version of Chrome in Windows 7)
By appending a data URI to the page, you can embed a document within the page that can be downloaded. The data portion of the string can be dynamically concatenated using Javascript. You can choose to format it as a URL encoded string or as base64 encoded. When it is base64 encoded, the browser will download the contents as a file. You will have to add a script or jQuery plugin to do the encoding. Here is an example with static data:
jQuery('body').prepend(jQuery('<a/>').attr('href','data:text/octet-stream;base64,SGVsbG8gV29ybGQh').text('Click to download'))
A PDF file? No. A txt file. Yes. With the recent HTML5 blob URIs. A very basic form of your code would look something like this:
window.URL = window.webkitURL || window.URL;
window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder;
var file = new window.BlobBuilder(),
number = Math.random().toString(); //In the append method next, it has to be a string
file.append(number); //Your random number is put in the file
var a = document.createElement('a');
a.href = window.URL.createObjectURL(file.getBlob('text/plain'));
a.download = 'filename.txt';
a.textContent = 'Download file!';
document.body.appendChild(a);
You can use the other methods mentioned in the other answers as a fallback, perhaps, since BlobBuilder probably isn't supported very well.
Demo
Note: BlobBuilder seems to be deprecated. Refer to this answer to see how to use Blob instead of BlobBuilder. Thanks to #limonte for the heads up.

How can I get a file's upload size using simple Javascript?

I have upload file functionality on one of the page. I check for the extension of the file using JavaScript. Now i want to restrict the user from uploading file greater than 1 MB. Is there any way i can check the file upload size using JavaScript.
My code currently look like this:
<script language="JavaScript">
function validate() {
var filename = document.getElementById("txtChooseFile").value;
var ext = getExt(filename);
if(ext == "txt" || ext == "csv")
return true;
alert("Please upload Text files only.");
return false;
}
function getExt(filename) {
var dot_pos = filename.lastIndexOf(".");
if(dot_pos == -1)
return "";
return filename.substr(dot_pos+1).toLowerCase();
}
</script>
See http://www.w3.org/TR/FileAPI/. It is supported by Firefox 3.6; I don't know about any other browsers.
Within the onchange event of a <input id="fileInput" type="file" /> simply:
var fi = document.getElementById('fileInput');
alert(fi.files[0].size); // maybe fileSize, I forget
You can also return the contents of the file as a string, and so forth. But again, this may only work with Firefox 3.6.
Now it is possible to get file size using pure JavaScript. Nearly all browser support FileReader, which you can use to read file size as well as you can show image without uploading file to server. link
Code:
var oFile = document.getElementById("file-input").files[0]; // input box with type file;
var img = document.getElementById("imgtag");
var reader = new FileReader();
reader.onload = function (e) {
console.log(e.total); // file size
img.src = e.target.result; // putting file in dom without server upload.
};
reader.readAsDataURL(oFile );
You can get file size directly from file object using following code.
var fileSize = oFile.size;
Other that aquiring the filename there is no way for you to find out any other details about the file in javascript including its size.
Instead you should configure server-side script to block an oversized upload.
Most of these answers are way out-of-date. It is currently possible to determine file size client-side in any browser that supports the File API. This includes, pretty much, all browsers other than IE9 and older.
It might be possible using a lot of browser-specific code. Take a look at the source of TiddlyWiki, which manages to save itself on the user's hard drive by hooking into Windows Scripting Host (IE), XPCOM (Mozilla), etc.
I don't think there is any way of doing that with plain JS from a web page.
With a browser extension maybe, but from a page javascript cannot access the filesystem for security reasons.
Flash and Java should have similar restrictions, but maybe they are a bit less strict.
not possible. would be a major security concern to allow client side scripts to run that can read file info from and end users hard drive.
See here:
http://www.kavoir.com/2009/01/check-for-file-size-with-javascript-before-uploading.html
As to all the people saying this has to be done server side, they are absolutely spot on it does.
In my case though the maximum size I will except is 128Mb, if a user tries to upload something that is 130Mb they should not have to wait the 5 minute upload time to find out it is too big so I need to do an additional check before they submit the page for usability sake.
I had the same issue, Here's a simple JavaScript snippet worked for me. Adding for future googlers.
HTML
<input type="file" name="photo" id="photo" accept="image/*">
JS
const file = document.getElementById('photo');
// Show KB (add one more /1024 for MB)
const filesize = file.files[0].size / 1024;
if (filesize > 500) { // Alert greater than 500kb
console.log(filesize);
alert('Please upload image less than 500 KB');
return;
}

Categories

Resources