I want to export an HTML canvas as an image on click of a button. My approach so far is to wrap the button in an anchor and onclick, send a request to my API to generate the save as dialog by setting the content-disposition
to attachment
for the response. Honestly I don't really need nor want to go to my server-side API for this because the canvas is in my client side code, but the only way I know of generating a 'save file' dialog is through setting the response header's content-disposition to attachment. The example here suggests using saveAs()
from FileSaver.js but our prof doesn't let us use any external libraries. Is there a way to generate the 'Save File' dialog from the front-end code similarly to saveAs() using pure JS. If not, what would be cleanest alternative to sending the canvas blob with my request and packaging it in an image in my back-end?
Thanks
UPDATE:
I managed to get it to the point where I'm able to download image files using various resources. The problem now is that the files I download are corrupt and I'm not sure what the problem might be. Here's some code:
Frontend:
editjs.downloadCanvas = function(fileBlob,filename){
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (this.readyState === XMLHttpRequest.DONE){
console.log(this.status);
if(this.status === 200){
var a = document.createElement('a');
document.getElementById('export_annotation').parentNode.appendChild(a);
console.log("created anchor - trying to trigger download");
a.href = "/export/pdfs/"+filename+"/canvases/page/"+filename+"-pg-"+pageNum;
a.click();
}
}
};
var formData = new FormData();
formData.append("file", fileBlob);
formData.append("name", filename+"-pg-"+pageNum);
var url = "/export/pdfs/"+filename+"/canvases/"+pageNum;
xhr.open("POST",url,true);
console.log("sending export data");
xhr.send(formData);
}
editjs.getContent = function(dataURL,filename,callback){
var req = new XMLHttpRequest;
req.open( 'GET', dataURL );
req.responseType = 'arraybuffer';
req.onload = function fileLoaded(e)
{
var mime = this.getResponseHeader('content-type');
callback(new Blob([this.response], {type:mime}),filename) ;
};
req.send();
}
BACKEND:
app.post('/export/pdfs/:fname/canvases/:page',upload.single("file"), function(req,res){
console.log("Creating export file!");
console.log(req.body.name);
if (req.session.user){
MongoClient.connect("mongodb://localhost:27017/test", function(err, db) {
if(err) res.status(500).end("Database error");
console.log("Connected to Database");
var tmp_file = {filename: req.body.name, file_path: req.file.path};
db.collection('canvases').save(tmp_file, function(err, record) {
if (err) res.status(500).end("Database error");
db.close();
return res.send();
});
});
console.log("exporting to:");
console.log(req.file.path);
}
else{return res.status(403).end("Forbidden");}
});
app.get('/export/pdfs/:fname/canvases/page/:storedfname', function(req,res){
if (req.session.user){
console.log("reading");
console.log(req.params.storedfname);
MongoClient.connect("mongodb://localhost:27017/test", function(err, db) {
if(err) res.status(500).end("Database error");
db.collection('canvases').findOne({filename: req.params.storedfname}, function(err, record) {
if (err) res.status(500).end("Database error");
console.log(record);
if (record){
db.close();
console.log("record found");
res.setHeader('Content-type','image/png');
res.setHeader('Content-disposition', "attachment; filename=" +req.params.storedfname+".png");
fs.createReadStream(record.file_path).pipe(res);
}
});
});
}
else{return res.status(403).end("Forbidden");}
});