I have a problem with .toDataURL()
for large canvas. I want to enconde in base64
and decode on php file but if I have a large canvas the strDataURI
variable is empty.
My code:
var strDataURI = canvas.toDataURL();
strDataURI = strDataURI.substr(22, strDataURI.length);
$.post("save.php",
{
str: strDataURI
};
Is there any alternative to .toDataURL()
or some way to change the size limit?
Thanks.
I'm not sure if there are limitation to canvas dimensions, but data urls have limitations depending on the browser: Data URL size limitations.
What you could try is using Node.js + node-canvas (server side) to recreate the canvas. I've been using these for creating printable images from canvas elements, and didn't have any problems/limitations using toDataURL so far.
Are you using the fabric.js library? I noticed you posted on their forum as well. Fabric.js can be used in Node.js and has a toDataURLWithMultiplier method, which scales the canvas/context allowing you to change the dataurl image size. You can check the method source to see how this is done.
Since you're using fabric.js I would suggest using Node.js to handle the canvas to image processing on the server. You'll find more info on how to use fabric.js on Node.js here.
Here is a simple server using Node.js and express:
var express = require('express'),
fs = require('fs'),
fabric = require('fabric').fabric,
app = express(),
port = 3000;
var allowCrossDomain = function (req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'POST, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
}
app.configure(function() {
app.use(express.bodyParser());
app.use(allowCrossDomain);
});
app.options('/', function(req, res) {
res.send(200);
});
app.post('/', function(req, res) {
var canvas = fabric.createCanvasForNode(req.body.width, req.body.height);
console.log('> Loading JSON ...');
canvas.loadFromJSON(req.body.json, function() {
canvas.renderAll();
console.log('> Getting PNG data ... (this can take a while)');
var dataUrl = canvas.toDataURLWithMultiplier('png', req.body.multiplier),
data = dataUrl.replace(/^data:image\/png;base64,/, '');
console.log('> Saving PNG to file ...');
var filePath = __dirname + '/test.png';
fs.writeFile(filePath, data, 'base64', function(err) {
if (err) {
console.log('! Error saving PNG: ' + err);
res.json(200, { error: 'Error saving PNG: ' + err });
} else {
console.log('> PNG file saved to: ' + filePath);
res.json(200, { success: 'PNG file saved to: ' + filePath });
}
});
});
});
app.listen(port);
console.log('> Server listening on port ' + port);
When the server is running you can send data to it (postData
).
The server expects json
, width
and height
to recreate the canvas, and a multiplier
to scale the data url image. The client side code would look something like this:
var postData = {
json: canvas.toJSON(),
width: canvas.getWidth(),
height: canvas.getHeight(),
multiplier: 2
};
$.ajax({
url: 'http://localhost:3000',
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(postData),
dataType: 'json',
success: function(data) {
console.log(data);
},
error: function(err) {
console.log(err);
}
});