How do I programmatically download a file created on the file with a Firefox WebExtension? - firefox-addon-webextensions

I am trying to port a Chrome Extension that programmatically creates and downloads a file to a Firefox WebExtension, using Firefox 45.0.1.
This is the Javascript code:
text = '{"greeting":"Hello, World!"}';
var a = document.createElement('a');
var file = new Blob([text], {type: 'text/json'});
a.href = URL.createObjectURL(file);
a.download = 'hello.world'; // Filename
a.click(); // Trigger download
All lines seem to execute fine, but no file is downloaded (I put a console.log() after the a.click()).
As of now there is no chrome.downloads API in Firefox WebExtensions.
Is there any incompatibility with Firefox in the code above? Is there any other alternative to programmatically download a file using a Firefox WebExtension?

One way to do this, would be to add an event listener to the a tag.
text = '{"greeting":"Hello, World!"}';
var a = document.createElement('a');
var file = new Blob([text], {type: 'text/json'});
a.href = URL.createObjectURL(file);
a.download = 'hello.world'; // Filename
a.addEventListener('click', dlLinkClicked);
function dlLinkClicked(e){
var link = e.currentTarget.href;
var filename = e.currentTarget.download;
/*downloadVidWithChromeApi downloads using the chrome download API,
otherwise returns false and starts downloading the file
using the html5 download - you don't have to do anything else*/
if(downloadVidWithChromeApi(link, filename)){
e.preventDefault();
}
}
function downloadVidWithChromeApi(link, fileName){
if(chrome.downloads && chrome.downloads.download){
chrome.downloads.download({
url: link,
saveAs: false,
filename: fileName // Optional
});
return true;
}else{
return false;
}
}
Notice that I use the downloadVidWithChromeApi function like so, to check if chrome.downloads is supported.
Therefore this code can run in both firefox, chrome, AND opera web extensions AS IS.

Related

How to save SURVEY PDF on the disk

I want to save somes PDF created with 'survey-pdf' on my disk.
Actually, i can send the PDF but i can't save it on my disk.
My final code :
return surveyPDF.save(filename);
Someone can help me ?
Thank you
Can you try
await surveyPDF.save(filename)
?
.save seems to be an asynchronous function that downloads the PDF file.
From the docs
Call save method of surveyPDF object to download file in browser. This is asynchronous method
#2 If the first method doesn't work, you can try this
function savePdfAsString() {
const surveyPDF = new SurveyPDF.SurveyPDF(json);
surveyPDF.data = survey.data;
surveyPDF
.raw("dataurlstring")
.then(function (text) {
//var file = new Blob([text], {type: "application/pdf"});
var a = document.createElement("a");
//a.href = URL.createObjectURL(file);
a.href = text;
a.download = "surveyAsString.pdf";
//document
// .body
// .appendChild(a);
a.click();
});
}
Here you are using the .raw function to transform the PDF into a dataurlstring and then downloading that. Here's the docs for this
*Not tested

Trigger CSV file download with Angular

This question has been asked a fair bit before, but none of the solutions I've seen seem to work, potentially because of the way I stream the file back to the browser. The CSV I ultimately want is in a private S3 bucket and because of security middleware, I have to get it via a NodeJS endpoint. The code for the API is below.
exports.download = function(req, res) {
var recording = req.vsRecording,
s3 = new AWS.S3();
if(recording.data_uri){
try{
res.set('Content-Type', 'application/octet-stream');
var fileStream = s3.getObject({Bucket: 'processing-dispatched', Key: recording._id + '/aggregated.csv'}).createReadStream();
fileStream.pipe(res);
}
catch(err){
res.status(500).json({error: err});
}
}
else {
res.status(500).json({error: 'Recording does not have a report file.'});
}
};
This works perfectly and I can get the content of the file back to the browser. When it goes wrong is trying to get that content into be opened as a file download. Is there a special way to handle downloading streams?
The closest I've got is this code on the client, which sometimes seems to work on localhost if I turn my adblocker off - but does not work in production.
$scope.download = function(){
Report.download($state.params.recordingId).then(function(data){
var csvContent = "data:text/csv;charset=utf-8," + data.toString();
var encodedUri = encodeURI(csvContent);
window.open(encodedUri);
});
Report.download is just an angular service wrapper around my Node endpoint, it returns a promise and resolves the content of the file in the data variable.
reason might be the browser blocking the new window.
Allow all sites to show pop-ups in browser setting.
you can try thing in different ways create a file in node with fs and return url to the Front-end
or
you can Try the following code
$scope.download = function() {
Report.download($state.params.recordingId).then(function(data) {
var csvContent = "data:text/csv;charset=utf-8," + data.toString();
var a = document.createElement('a');
a.href = "data:application/csv;charset=utf-8," + csvContent;
a.setAttribute('download', "abc.csv");
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
});
}

PDF file name not taken into account in IE10 / Edge

Using this code, i have the pdf's name that is incorrect : A string of random letters like a uuid.
This problem seems to only be with IE 10 / Edge.
AngularJS's version 1.4.7
this.downloadPdf = function(pdfName){
console.log(pdfName);
$http.get(config.UrlApi + "/pdf/"+ pdfName.nameFile, { responseType: 'arraybuffer' });
var a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.target = '_blank';
a.download = pdfName.name;
document.body.appendChild(a);
a.click();
});
Use the Blob Interface:
function build(response)
{
var bb = new Blob([response.data], { type: "application/pdf"});
if (URL && URL.hasOwnProperty("createObjectURL") )
{
var url = URL.createObjectURL(bb);
}
else if (window.navigator.msSaveOrOpenBlob)
{
window.navigator.msSaveOrOpenBlob(bb, 'foo.pdf');
}
}
$http.get(config.UrlApi + "/pdf/"+ pdfName.nameFile, { responseType: 'arraybuffer' }).then(build);
Blob urls are subject to an origin policy. This means that they can only be used in documents that have the same site-of-origin as the document running the script that created the url. If you need to use the blob object from an <iframe> that is running in a different domain, you must use the postMessage API to send the blob data to the frame and then create the blob: url there.
References
Saving files locally using Blob and msSaveBlob
New Blob Constructor in IE10
Edge Doesn't Use download attribute to set filename for blob URI downloading
Blob Object
URL.createObjectURL
MSDN: JavaScript Version Information

Download a file which does not exists in project directory in AngularJS

In my project i just wanted to implement upload and download features. I have done upload functionality with AngularJS and Node.js. But here the problem is to upload a file(.pdf, all image formats) into somewhere in the system. Say for example, my project is located in D drive. Though i have to upload a file into C drive or some other drive in my computer and i have done it successfully. But when i try to read the file location from Node.js and pass the path to angular, everything is ok and file is downloaded in the browser. when i try to open a downloaded file it sends back a response - fatal error/ nothing to show. I have tried with blob only when i send a filestream instead a path to Angular.
The code is as follows
var file = new Blob([data], {type: 'application/pdf'});
var fileURL = URL.createObjectURL(file);
window.open(fileURL);
where data is a file stream response from the server.
not my code but try this to save a BLOB:
var saveData = (function () {
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
return function (data, fileName) {
var json = JSON.stringify(data),
blob = new Blob([json], {type: "octet/stream"}),
url = window.URL.createObjectURL(blob);
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);
Source: http://jsfiddle.net/koldev/cw7w5/
If you want to force the download of a linked file you could use the HTML5 a option download
<a download="filename_for_download" href="path/to/the/file"> Clicking o will force a download</a>
Some more information: https://developers.google.com/web/updates/2011/08/Downloading-resources-in-HTML5-a-download?hl=en
keep the (not existing) support of older browsers in mind
One Note: Your upload process ("to upload a file into C drive or some other drive in my computer") sounds like it may be improved or rethought.

Save PDF file loaded in iframe

I am trying to save a pdf file that is loaded in an iFrame. There is by default a button in the iFrame to save the file but I want an extra button (outside the iFrame) to save the file.
<iframe id="labelFrame" src="loadedFile.pdf"></iframe>
<button id="savePDF">Download File</button>
In javascript:
$('#savePDF').click(function(){
var save = document.getElementById('labelFrame');
//Save the file by opening the explorer for the user to select the place to save or save the file in a default location, how do I do this?
}
What is the best way to reach this?
I needed an answer to this question as well and found a solution.
When displaying a PDF in an IFrame the browser will render it in an <embed> element and from there we cant use it in javascript as far as i know.
We'll need to use XMLHttpRequest to get the PDF from a server as a Blob object only then we can both display it and save it using javascript.
var iframe = document.getElementById('labelFrame'),
saveBtn = document.getElementById('savePDF'),
pdfUrl = 'loadedFile.pdf';
var xhr = new XMLHttpRequest();
xhr.open("GET", pdfUrl);
xhr.responseType = 'blob'; // <- important (but since IE10)
xhr.onload = function() {
var blobUrl = URL.createObjectURL(xhr.response); // <- used for display + download
iframe.src = blobUrl
saveBtn.onclick = function() {
downloadBlob(blobUrl, 'myFilename.pdf');
}
};
xhr.send();
The xhr.onload function will set to src of the iframe and add the onclick handler to the save button
Here is the downloadBlob() function that i've used in the example
function downloadBlob(blobUrl, filename) {
var a = document.createElement('a');
a.href = blobUrl;
a.target = '_parent';
// Use a.download if available. This increases the likelihood that
// the file is downloaded instead of opened by another PDF plugin.
if ('download' in a) {
a.download = filename;
}
// <a> must be in the document for IE and recent Firefox versions,
// otherwise .click() is ignored.
(document.body || document.documentElement).appendChild(a);
a.click();
a.remove();
}

Resources