我想使用fabric.js将Canvas下载为PNG。在下载时我想缩放图像。所以我使用multiplier
函数的toDataURL()
属性。但我得到失败 - 网络错误
PS:如果我不提供multiplier
属性,则会下载,但我执行想要使用multiplier
属性,因为我必须进行扩展图像
这就是我在做的事情:
HTML代码:
<canvas width="400" height="500" id="canvas" ></canvas>
<a id='downloadPreview' href="javascript:void(0)"> Download Image </a>
JS
document.getElementById("downloadPreview").addEventListener('click', downloadCanvas, false);
var _canvasObject = new fabric.Canvas('canvas');
var downloadCanvas = function(){
var link = document.createElement("a");
link.href = _canvasObject.toDataURL({format: 'png', multiplier: 4});
link.download = "helloWorld.png";
link.click();
}
答案 0 :(得分:33)
你面临的问题与fabricjs(也不是画布,甚至javascript btw)没有直接关系,而是来自某些浏览器(包括Chrome)对src
属性的最大长度的限制。具有donwload属性的锚元素(<a>
)。
当达到此限制时,您唯一得到的就是控制台中无法捕获的“网络错误”;下载失败,但你作为开发人员无法了解它。
正如(你拒绝标记为) duplicate所提出的,解决方案是在可用时直接获取Blob(对于画布,你可以调用其toBlob()
方法,或首先将dataURI转换为Blob,然后从此Blob创建object URL。
Fabricjs似乎还没有实现toBlob
功能,因此在您的确切情况下,您必须执行此操作。
您可以找到许多脚本来将dataURI转换为Blob,其中一个脚本可以在MDN's polyfill到Canvas.toBlob()
方法中使用。
然后它会是这样的:
// edited from https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob#Polyfill
function dataURIToBlob(dataURI, callback) {
var binStr = atob(dataURI.split(',')[1]),
len = binStr.length,
arr = new Uint8Array(len);
for (var i = 0; i < len; i++) {
arr[i] = binStr.charCodeAt(i);
}
callback(new Blob([arr]));
}
var callback = function(blob) {
var a = document.createElement('a');
a.download = fileName;
a.innerHTML = 'download';
// the string representation of the object URL will be small enough to workaround the browser's limitations
a.href = URL.createObjectURL(blob);
// you must revoke the object URL,
// but since we can't know when the download occured, we have to attach it on the click handler..
a.onclick = function() {
// ..and to wait a frame
requestAnimationFrame(function() {
URL.revokeObjectURL(a.href);
});
a.removeAttribute('href')
};
};
dataURIToBlob(yourDataURL, callback);
答案 1 :(得分:13)
我明白了。按照Kaiido的建议进行了解决。
function dataURLtoBlob(dataurl) {
var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {type:mime});
}
注意:从HTML5 / Javascript - DataURL to Blob & Blob to DataURL
获得上述功能var downloadCanvas = function(){
var link = document.createElement("a");
var imgData = _canvasObject.toDataURL({ format: 'png',
multiplier: 4});
var strDataURI = imgData.substr(22, imgData.length);
var blob = dataURLtoBlob(imgData);
var objurl = URL.createObjectURL(blob);
link.download = "helloWorld.png";
link.href = objurl;
link.click();
}
答案 2 :(得分:1)
由于前两个答案仅适用于具有base64数据的dataURL,并且由于href属性太大而导致此答案被与“网络错误”相关的更一般问题引用,这里是我正在使用的代码:
// must be called in a click handler or some other user action
var download = function(filename, dataUrl) {
var element = document.createElement('a')
var dataBlob = dataURLtoBlob(dataUrl)
element.setAttribute('href', URL.createObjectURL(dataBlob))
element.setAttribute('download', filename)
element.style.display = 'none'
document.body.appendChild(element)
element.click()
var clickHandler;
element.addEventListener('click', clickHandler=function() {
// ..and to wait a frame
requestAnimationFrame(function() {
URL.revokeObjectURL(element.href);
})
element.removeAttribute('href')
element.removeEventListener('click', clickHandler)
})
document.body.removeChild(element)
}
// from Abhinav's answer at https://stackoverflow.com/questions/37135417/download-canvas-as-png-in-fabric-js-giving-network-error/
var dataURLtoBlob = function(dataurl) {
var parts = dataurl.split(','), mime = parts[0].match(/:(.*?);/)[1]
if(parts[0].indexOf('base64') !== -1) {
var bstr = atob(parts[1]), n = bstr.length, u8arr = new Uint8Array(n)
while(n--){
u8arr[n] = bstr.charCodeAt(n)
}
return new Blob([u8arr], {type:mime})
} else {
var raw = decodeURIComponent(parts[1])
return new Blob([raw], {type: mime})
}
}
使用这些功能,您可以将代码更改为:
document.getElementById("downloadPreview").addEventListener('click', function() {
var dataURL = _canvasObject.toDataURL({format: 'png', multiplier: 4})
download("hellowWorld.png", dataURL)
})
答案 3 :(得分:0)
我的网站上有多个画布,其中一个出现了相同的问题。
画布尺寸1:750像素x 500像素(Window Chrome出现网络问题,在Chrome Macos上工作正常)
画布尺寸2:540px x 1080px(没有下载问题,可与乘数4配合使用)
我只是减小了下载大小,将乘数4更改为2,就可以了。
然后我将乘数更改为3,它不再起作用。
然后我尝试了2.5,它再次正常工作。
使用4乘数创建如此大的文件不是我的要求,所以我选择了2.5。
这是解决此问题的最简单,最快的方法。
答案 4 :(得分:0)
就我而言,我只是使用了
var callback = function(blob) {
var a = document.createElement('a');
var saveAs = $('input[name="extensionGrp"]:checked').val();
var link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = 'Image.' + saveAs;
document.body.appendChild(link);
link.click();
};