How can I make a browser display a "save as dialog" so the user can save the content of a string to a file on his system?
For example:
var myString = "my string with some stuff";
save_to_filesystem(myString,"myString.txt");
Resulting in something like this:
EDIT 2022: Please see other answers regarding File System API
In case anyone is still wondering...
I did it like this:
Save
can't remember my source but it uses the following techniques\features:
html5 download attribute
data URI's
Found the reference:
http://paxcel.net/blog/savedownload-file-using-html5-javascript-the-download-attribute-2/
EDIT:
As you can gather from the comments, this does NOT work in
Internet Explorer (however works in Edge v13 and later)
Opera Mini
http://caniuse.com/#feat=download
There is a new spec called the Native File System API that allows you to do this properly like this:
const result = await window.chooseFileSystemEntries({ type: "save-file" });
There is a demo here, but I believe it is using an origin trial so it may not work in your own website unless you sign up or enable a config flag, and it obviously only works in Chrome. If you're making an Electron app this might be an option though.
There is a javascript library for this, see FileSaver.js on Github
However the saveAs() function won't send pure string to the browser, you need to convert it to blob:
function data2blob(data, isBase64) {
var chars = "";
if (isBase64)
chars = atob(data);
else
chars = data;
var bytes = new Array(chars.length);
for (var i = 0; i < chars.length; i++) {
bytes[i] = chars.charCodeAt(i);
}
var blob = new Blob([new Uint8Array(bytes)]);
return blob;
}
and then call saveAs on the blob, as like:
var myString = "my string with some stuff";
saveAs( data2blob(myString), "myString.txt" );
Of course remember to include the above-mentioned javascript library on your webpage using <script src=FileSaver.js>
This is possible using this cross browser javascript implementation of the HTML5 saveAs function: https://github.com/koffsyrup/FileSaver.js
If all you want to do is save text then the above script works in all browsers(including all versions of IE), using nothing but JS.
Solution using only javascript
function saveFile(fileName,urlFile){
let a = document.createElement("a");
a.style = "display: none";
document.body.appendChild(a);
a.href = urlFile;
a.download = fileName;
a.click();
window.URL.revokeObjectURL(url);
a.remove();
}
let textData = `El contenido del archivo
que sera descargado`;
let blobData = new Blob([textData], {type: "text/plain"});
let url = window.URL.createObjectURL(blobData);
//let url = "pathExample/localFile.png"; // LocalFileDownload
saveFile('archivo.txt',url);
Using showSaveFilePicker():
const handle = await showSaveFilePicker({
suggestedName: 'name.txt',
types: [{
description: 'Text file',
accept: {'text/plain': ['.txt']},
}],
});
const blob = new Blob(['Some text']);
const writableStream = await handle.createWritable();
await writableStream.write(blob);
await writableStream.close();
Inspired by #ronald-coarite answer, here is my solution:
function saveTxtToFile(fileName: string, textData: string) {
const blobData = new Blob([textData], { type: 'text/plain' });
const urlToBlob = window.URL.createObjectURL(blobData);
const a = document.createElement('a');
a.style.setProperty('display', 'none');
document.body.appendChild(a);
a.href = urlToBlob;
a.download = fileName;
a.click();
window.URL.revokeObjectURL(urlToBlob);
a.remove();
}
saveTxtToFile('myFile.json', JSON.stringify(myJson));
Related
Hope there hadn't any question same as mine.
I tried to write some share screen and screen record. For that I found others code to study.
In the code, it used the video filename extension is .webm. I tried to change it to .mp4 but failed.
I thought that video/webm and video/mp4 were both valid. But not know why, when I changed filename extension, it got worse.
Is there anything wrong I didn't find? I had tried some keywords to search (for example, video/webm mp4) but had no result. I would like to know if my keyword direction is wrong?
Thankyou.
The following is part of the code:
btnPlay.onclick = () => {
var blob = new Blob(buffer, { type: 'video/webm' })
recvideo.src = window.URL.createObjectURL(blob)
recvideo.srcObject = null
recvideo.controls = true
recvideo.play()
}
// download record
btnDownload.onclick = () => {
var blob = new Blob(buffer, { type: 'video/webm' })
var url = window.URL.createObjectURL(blob)
var a = document.createElement('a')
a.href = url
a.style.display = 'none'
a.download = 'video.webm'
a.click()
}
In the code, I only changed webm to mp4.
The code source: https://ithelp.ithome.com.tw/articles/10273368?sc=iThomeR
I can not quite wrap my head around on how to download a PDF from a google spreadsheet PDF Export Weblink. I generated a testing spreadsheet for this case.
I understand that I need to implement encodeURIComponent and/or "Buffer.from" to the blob but however I do it, it only downloads a broken PDF for me.
This is what I currently have in its rawest form. Thank you for your support!
Node JS:
const fetch = require('node-fetch');
var url = "https://docs.google.com/spreadsheets/d/1fLjKASR_g5wsvOjjJi6RclqMVd2o_1On-OfimXtId4E/export?exportFormat=pdf&format=pdf&size=A4&fzr=true&gid=477517973&sheetnames=false&printtitle=false&pagenumbers=false&gridlines=false&portrait=true&fitw=true&fith=true&top_margin=0.20&bottom_margin=0.20&left_margin=0.20&right_margin=0.20";
let blob = await fetch(url).then(r => r.blob());
// then send blob variable to javascript
Javascript:
function downloadURI(name) {
var uri = 'data:application/pdf;base64,' + blob;
var link = document.createElement('a');
link.download = name;
link.href = uri;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
delete link;
}
downloadURI("test"+".pdf")
I thought that from var uri = 'data:application/pdf;base64,' + blob; in your script, in this case, it is required to convert the downloaded data as the base64. Although I'm not sure about the relationship between the scripts between Node JS: and Javascript:, in your situation, how about the following modification?
From:
let blob = await fetch(url).then(r => r.blob());
To:
let buf = await fetch(url).then((r) => r.arrayBuffer());
const data = Buffer.from(buf).toString("base64");
By this, you can use data as follows.
var uri = 'data:application/pdf;base64,' + data;
Note:
As the additional information, for example, if you want to download your Spreadsheet as a PDF file using only Javascript, you can also use the following script. But, in this case, the Spreadsheet is required to be publicly shared. Please be careful about this.
async function downloadURI(name) {
var url = "https://docs.google.com/spreadsheets/d/1fLjKASR_g5wsvOjjJi6RclqMVd2o_1On-OfimXtId4E/export?exportFormat=pdf&format=pdf&size=A4&fzr=true&gid=477517973&sheetnames=false&printtitle=false&pagenumbers=false&gridlines=false&portrait=true&fitw=true&fith=true&top_margin=0.20&bottom_margin=0.20&left_margin=0.20&right_margin=0.20";
let blob = await fetch(url).then((r) => r.blob());
var f = new FileReader();
f.readAsDataURL(blob);
f.onload = d => {
var uri = d.target.result;
var link = document.createElement('a');
link.download = name;
link.href = uri;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
delete link;
}
}
downloadURI("test"+".pdf")
Hi I am a beginner so I am not having much knowledge about javascript so kindly help me in solving my issue.
I am facing problem in saving audio input. The audio which is saved onto the disk is somehow corrupted and not proper (.mp3/.wav) file.
Here is my javascript code
function saveBlob(blob, fileName) {
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
var url = window.URL.createObjectURL(blob);
a.href = url;
a.download = fileName;
a.click();
window.URL.revokeObjectURL(url);
}
function startRecording(){
var device = navigator.mediaDevices.getUserMedia({audio:true});
var items = [];
device.then( stream => {
var recorder = new MediaRecorder(stream);
recorder.ondataavailable = e => {
items.push(e.data);
if(recorder.state == "inactive")
{
var blob = new Blob(items, {type: 'audio/wav'});
alert(blob.type);
saveBlob(blob, 'myRecording.wav');
}
}
recorder.start();
setTimeout(()=>{
recorder.stop();
}, 4000);
});
I think the problem is that you save the file with the wrong mimeType. As far as I know there is no browser which can record WAV files out of the box.
A quick fix would be to change the part which creates the file.
var blob = new Blob(items, {type: recorder.mimeType});
alert(blob.type);
saveBlob(blob, `myRecording.wav${blob.type.split('/')[1].split(';')[0]}`);
Or you could use a package like extendable-media-recorder which allows to record WAV files directly.
I have a POST call that returns a base64 PDF. When I call this endpoint I convert it to a Blob and then download it. This works fine in all browsers except for Safari.
openPdf = () => {
const sendObj = {
fakeValue: 'test'
};
axios.post('https://fakeendpoint.com/create-pdf', sendObj)
.then((res) => {
const base64URL = res.data;
const binary = atob(base64URL.replace(/\s/g, ''));
const len = binary.length;
const buffer = new ArrayBuffer(len);
const view = new Uint8Array(buffer);
for (let i = 0; i < len; i += 1) {
view[i] = binary.charCodeAt(i);
}
// create the blob object with content-type "application/pdf"
const blob = new Blob([view], { type: 'application/pdf' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
document.body.appendChild(a);
a.style = 'display: none';
a.href = url;
a.download = 'Test.pdf';
a.target = '_blank';
a.click();
});
}
How can I get this to work in Safari?
Seems like Safari doesn't follow the standards for the a tag. I believe this previous SO post identifies the root cause. From the comments in the linked answer:
Note that specifying a target attribute in Safari seems to override the download attribute (this does not seem to be the case in Chrome, Firefox or Opera).
Try removing a.target = '_blank' in your code above and then testing it. It should work!
Unfortunately, I'm not sure how you would open it in a new tab with that change.
from a test I made - this occurs only when the PDF is too big. (and only on mobile Safari)
I assume it is related to the length of the URL.
The only drawback from removing target="_blank" is that if the user click on "back" it will loose the previous page state.
I read few older thread about the same, but seen the file API changed a lot recently. My requirement is to save a json file (data is locally in indexdDB, but I need a way to back it up). Since I use indexdDB, I only target recent browsers, mainly chrome. So, it it possible to save data (json string) to client computer?
I have seen http://eligrey.com/demos/FileSaver.js/ , but is there a way to do it natively?
Thanks.
You can use a Blob and the HTML5 a[download] feature to provide a JSON backup download:
var data = {a:1, b:2, c:3};
var json = JSON.stringify(data);
var blob = new Blob([json], {type: "application/json"});
var url = URL.createObjectURL(blob);
var a = document.createElement('a');
a.download = "backup.json";
a.href = url;
a.textContent = "Download backup.json";
Here is a jsfiddle example: http://jsfiddle.net/potatosalad/yuM2N/
Yes, you can. This assumes that you have the json in text:
var toDownload=new Blob([text],{type:'x-whatever/x-backup'});
var link=window.URL.createObjectURL(toDownload);
window.location=link;
that is untested, but it should work.
You can use FileSaver.js.
Sample code:
//include the js file in html.
<script src="FileSaver.min.js"></script>
// other code ...
//use it here.
var myjson= "{a:3, b:4}";
var blob = new Blob([myjson], {type: "application/json"});
var saveAs = window.saveAs;
saveAs(blob, "my_outfile.json");
Use JSON.stringify to create a string from JSON.
Fiddle: https://jsfiddle.net/9w9ofec4/3/
based on potatosalad answer i experimented with an 'self' updating link:
jsfiddle
function saveAsFile(link, content, filename) {
var blob = new Blob([content], {type: "text/text"});
var url = URL.createObjectURL(blob);
// update link to new 'url'
link.download = filename + ".txt";
link.href = url;
}
saveAsFile(this, "YourContent", "HelloWorldFile");
the function saveAsFile() needs the calling a element as first argument.
than it updates the href target to the new blob.
function saveAsJSON(data, name=Date.now()+'.json') {
const a = document.createElement('a')
a.download = name
a.href = URL.createObjectURL(new Blob([JSON.stringify(data)], {type: 'application/json'}))
a.click()
}
// https://stackoverflow.com/questions/62371219/chrome-stops-download-files-from-stackoverflow-snippets
saveAsJSON(['orange', 'banana', {name: 'apple'}])
To save the file with a custom name, you can create a hidden <a> element and then click on it. This method is used by FileSaver.js.
function download(name, text){
var toDownload=new Blob([text],
{type:'data:application/octet-stream'});
var link = window.URL.createObjectURL(toDownload);
var el = document.createElement("a");
el.href = link;
el.download = name;
el.click();
window.URL.revokeObjectURL(link);
}