2016-05-10 6 views
14

Ich möchte Canvas als PNG mit Fabric.js herunterladen. Während des Downloads möchte ich das Bild skalieren. So verwende ich multiplier Eigenschaft von toDataURL() Funktion. Aber ich bekomme Fehlgeschlagen-NetzwerkfehlerDownload Canvas als PNG in fabric.js geben Netzwerk Fehler

PS: Wenn ich multiplier Eigenschaft nicht geben, es ist das Herunterladen, aber ich tun wollen multiplier Eigenschaft verwenden, da ich das Bild zu skalieren haben

Dies ist, was ich tue:

HTML-Code:

<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

Haben Sie diesen Fehler nur bei Chrome? Wenn dies der Fall ist, hängt dies wahrscheinlich zusammen: http: // stackoverflow.com/questions/36918075/is-it-possible-zu-programmatically-detect-size-limit-fuer-daten-url/36951356 aber für den gebrauchsfall, anstatt toBlob zu nennen (was ich nicht für möglich halte In fabricjs) müssen Sie das dataURI in ein Blob konvertieren, bevor Sie die href des Ankers auf die Objekt-URL dieses Blobs setzen. (Sie können [MDNs Polyfill für 'toBlob' überprüfen (https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob#Polyfill) und wählen Sie ihre Art der Umwandlung eines DataURI in ein Blob) – Kaiido

+0

Muss ich nur den Wert für "href to blob" setzen? – Abhinav

+0

Nein zu einer Objekt-URL, die aus dem Blob erstellt wurde ('URL.createObjectURL (blob)'). Überprüfen Sie die Antwort auf den vorgeschlagenen Betrogenen. – Kaiido

Antwort

19

Das Problem, das Sie ist konfrontiert sind nicht direkt mit fabricjs bezogen, (noch Leinwand und nicht einmal Javascript btw) , kommt aber von Einschränkungen, die einige Browser (einschließlich Chrome) auf die maximale Länge für das src-Attribut eines Anchor-Elements (<a>) mit dem donwload-Attribut haben.

Wenn dieses Limit erreicht ist, dann ist das einzige, was Sie haben, dieser unzugängliche "Network Error" in der Konsole; der Download ist fehlgeschlagen, aber Sie als Entwickler können davon nichts wissen.

Wie in dieser vorgeschlagen (Sie-verweigerte-to-mark-as-)duplicate ist die Lösung entweder erhalten direkt einen Blob, wenn verfügbar (für die Leinwand, können Sie seine toBlob() Methode aufrufen, oder zum ersten convert Ihre dataURI auf einen Fleck, und dann ein object URL von diesem Blob erstellen.

Fabricjs keine toBlob Funktion noch nicht umgesetzt zu haben scheinen, so in Ihrem genauen Fall, werden Sie das später tun.
Sie kann viele Skripts finden, um DataURI in Blob zu konvertieren, eine ist in MDN's polyfill zu Canvas.toBlob() Methode verfügbar.

Dann würde es so aussehen:

// 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); 
+0

Vielen Dank für eine detaillierte – Abhinav

+0

Ihr DataURIToBlob ist nicht gut gebildet. Wo ist Typ oder Qualität definiert? Und 'this 'referenziert das Fenster am wahrscheinlichsten. –

+0

@BT, Sie haben völlig Recht, ich weiß nicht, wie es so lange geblieben sein könnte, ohne dass es jemand bemerkt hat (ich der Erste). Vielen Dank. Aber ich sollte wahrscheinlich diese dataURIToBlob-Funktion jetzt entfernen, da 'toBlob' in den meisten Hauptbrowsern seinen Weg gefunden hat, es ist viel schneller als das Konvertieren der doppelten Daten. – Kaiido

9

Ich habe es. Arbeitete es aus wie

von Kaiido vorgeschlagen
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}); 
} 

HINWEIS: Haben Sie die obige Funktion von 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(); 
} 
+0

Ich habe diesen Code gut in Chrome und Edge, aber in FF passiert nichts. Weißt du, ob das für dich in FF funktioniert hat? – Ron

+0

Es ist heute für mich, also kann ich nicht überprüfen und sage Ihnen jetzt, aber ich denke, es funktionierte in FF, ich werde sowieso wieder überprüfen ASAP – Abhinav

+1

Awesome. Hatte das gleiche Problem und löste es mit Ihrer Lösung. Vielen Dank! – Steevie

1

Da die letzten beiden Antworten nur für dataURLs arbeiten, die Base64-Daten haben, und weil diese Antwort wurde durch allgemeinere Fragen im Zusammenhang mit „Netzwerkfehler“ verwiesen worden, weil der href Attribute, die zu groß sind, hier ist der Code ich verwende:

// 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}) 
    } 
} 

Mit diesen Funktionen können Sie den Code, um diese Änderung:

document.getElementById("downloadPreview").addEventListener('click', function() { 
    var dataURL = _canvasObject.toDataURL({format: 'png', multiplier: 4}) 
    download("hellowWorld.png", dataURL) 
}) 
+0

Sollte die verknüpfte Frage nicht stattdessen erneut geöffnet werden? (Zumindest, wenn es geschlossen wurde) Dies bietet nicht zu viele hilfreiche Informationen zu der aktuellen Frage: "Download Canvas als PNG in fabric.js". Es gibt keine andere Möglichkeit, eine Daten-URL zu erhalten, die eine PNG-Datei repräsentiert, als durch base64-Codierung der Binärdaten. – Kaiido