2012-10-09 18 views
9

mam unsing wtyczki canvas2Image.js:Canavas2Image.js zapisać base64 img jako png pośrednictwem elementu kliknij

/* 
* Canvas2Image v0.1 
* Copyright (c) 2008 Jacob Seidelin, [email protected] 
* MIT License [http://www.opensource.org/licenses/mit-license.php] 
*/ 

var Canvas2Image = (function() { 

    // check if we have canvas support 
    var bHasCanvas = false; 
    var oCanvas = document.createElement("canvas"); 
    if (oCanvas.getContext("2d")) { 
     bHasCanvas = true; 
    } 

    // no canvas, bail out. 
    if (!bHasCanvas) { 
     return { 
      saveAsBMP : function(){}, 
      saveAsPNG : function(){}, 
      saveAsJPEG : function(){} 
     } 
    } 

    var bHasImageData = !!(oCanvas.getContext("2d").getImageData); 
    var bHasDataURL = !!(oCanvas.toDataURL); 
    var bHasBase64 = !!(window.btoa); 

    var strDownloadMime = "image/octet-stream"; 

    // ok, we're good 
    var readCanvasData = function(oCanvas) { 
     var iWidth = parseInt(oCanvas.width); 
     var iHeight = parseInt(oCanvas.height); 
     return oCanvas.getContext("2d").getImageData(0,0,iWidth,iHeight); 
    } 

    // base64 encodes either a string or an array of charcodes 
    var encodeData = function(data) { 
     var strData = ""; 
     if (typeof data == "string") { 
      strData = data; 
     } else { 
      var aData = data; 
      for (var i=0;i<aData.length;i++) { 
       strData += String.fromCharCode(aData[i]); 
      } 
     } 
     return btoa(strData); 
    } 

    // creates a base64 encoded string containing BMP data 
    // takes an imagedata object as argument 
    /*var createBMP = function(oData) { 
     var aHeader = []; 

     var iWidth = oData.width; 
     var iHeight = oData.height; 

     aHeader.push(0x42); // magic 1 
     aHeader.push(0x4D); 

     var iFileSize = iWidth*iHeight*3 + 54; // total header size = 54 bytes 
     aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize/256); 
     aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize/256); 
     aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize/256); 
     aHeader.push(iFileSize % 256); 

     aHeader.push(0); // reserved 
     aHeader.push(0); 
     aHeader.push(0); // reserved 
     aHeader.push(0); 

     aHeader.push(54); // dataoffset 
     aHeader.push(0); 
     aHeader.push(0); 
     aHeader.push(0); 

     var aInfoHeader = []; 
     aInfoHeader.push(40); // info header size 
     aInfoHeader.push(0); 
     aInfoHeader.push(0); 
     aInfoHeader.push(0); 

     var iImageWidth = iWidth; 
     aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth/256); 
     aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth/256); 
     aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth/256); 
     aInfoHeader.push(iImageWidth % 256); 

     var iImageHeight = iHeight; 
     aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight/256); 
     aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight/256); 
     aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight/256); 
     aInfoHeader.push(iImageHeight % 256); 

     aInfoHeader.push(1); // num of planes 
     aInfoHeader.push(0); 

     aInfoHeader.push(24); // num of bits per pixel 
     aInfoHeader.push(0); 

     aInfoHeader.push(0); // compression = none 
     aInfoHeader.push(0); 
     aInfoHeader.push(0); 
     aInfoHeader.push(0); 

     var iDataSize = iWidth*iHeight*3; 
     aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize/256); 
     aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize/256); 
     aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize/256); 
     aInfoHeader.push(iDataSize % 256); 

     for (var i=0;i<16;i++) { 
      aInfoHeader.push(0); // these bytes not used 
     } 

     var iPadding = (4 - ((iWidth * 3) % 4)) % 4; 

     var aImgData = oData.data; 

     var strPixelData = ""; 
     var y = iHeight; 
     do { 
      var iOffsetY = iWidth*(y-1)*4; 
      var strPixelRow = ""; 
      for (var x=0;x<iWidth;x++) { 
       var iOffsetX = 4*x; 

       strPixelRow += String.fromCharCode(aImgData[iOffsetY+iOffsetX+2]); 
       strPixelRow += String.fromCharCode(aImgData[iOffsetY+iOffsetX+1]); 
       strPixelRow += String.fromCharCode(aImgData[iOffsetY+iOffsetX]); 
      } 
      for (var c=0;c<iPadding;c++) { 
       strPixelRow += String.fromCharCode(0); 
      } 
      strPixelData += strPixelRow; 
     } while (--y); 

     var strEncoded = encodeData(aHeader.concat(aInfoHeader)) + encodeData(strPixelData); 

     return strEncoded; 
    } 
*/ 

    // sends the generated file to the client 
    var saveFile = function(strData) { 
     document.location.href = strData; 
    } 

    var makeDataURI = function(strData, strMime) { 
     return "data:" + strMime + ";base64," + strData; 
    } 

    // generates a <img> object containing the imagedata 
    var makeImageObject = function(strSource) { 
     var oImgElement = document.createElement("img"); 
     oImgElement.src = strSource; 
     return oImgElement; 
    } 

    var scaleCanvas = function(oCanvas, iWidth, iHeight) { 
     if (iWidth && iHeight) { 
      var oSaveCanvas = document.createElement("canvas"); 
      oSaveCanvas.width = iWidth; 
      oSaveCanvas.height = iHeight; 
      oSaveCanvas.style.width = iWidth+"px"; 
      oSaveCanvas.style.height = iHeight+"px"; 

      var oSaveCtx = oSaveCanvas.getContext("2d"); 

      oSaveCtx.drawImage(oCanvas, 0, 0, oCanvas.width, oCanvas.height, 0, 0, iWidth, iHeight); 
      return oSaveCanvas; 
     } 
     return oCanvas; 
    } 

    return { 

     saveAsPNG : function(oCanvas, bReturnImg, iWidth, iHeight) { 
      if (!bHasDataURL) { 
       return false; 
      } 
      var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight); 
      var strData = oScaledCanvas.toDataURL("image/png"); 
      if (bReturnImg) { 
       return makeImageObject(strData); 
      } else { 
       saveFile(strData.replace("image/png", strDownloadMime)); 
      } 
      return true; 
     }, 

     saveAsJPEG : function(oCanvas, bReturnImg, iWidth, iHeight) { 
      if (!bHasDataURL) { 
       return false; 
      } 

      var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight); 
      var strMime = "image/jpeg"; 
      var strData = oScaledCanvas.toDataURL(strMime); 

      // check if browser actually supports jpeg by looking for the mime type in the data uri. 
      // if not, return false 
      if (strData.indexOf(strMime) != 5) { 
       return false; 
      } 

      if (bReturnImg) { 
       return makeImageObject(strData); 
      } else { 
       saveFile(strData.replace(strMime, strDownloadMime)); 
      } 
      return true; 
     }, 

    /* saveAsBMP : function(oCanvas, bReturnImg, iWidth, iHeight) { 
      if (!(bHasImageData && bHasBase64)) { 
       return false; 
      } 

      var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight); 

      var oData = readCanvasData(oScaledCanvas); 
      var strImgData = createBMP(oData); 
      if (bReturnImg) { 
       return makeImageObject(makeDataURI(strImgData, "image/bmp")); 
      } else { 
       saveFile(makeDataURI(strImgData, strDownloadMime)); 
      } 
      return true; 
     }*/ 
    }; 

})(); 

w html zrobić:

<script type="text/javascript"> 
    $(document).ready(function(){ 
    var _txt = "hey"; 
    $('#qrcode').qrcode({ 
     text :_txt 
    }); 
    $("#qrcode-canvas").attr("download","file.png"); 
    var oCanvas = document.getElementById("qrcode-canvas"); 
    $("#download-qrcode").on('click',function(){ 
     Canvas2Image.saveAsPNG(oCanvas); 
    }) 
    }); 
    </script> 

<div id="qrcode" class="" style="" ></div> 
<a class="btn btn-large btn-inverse" id="download-qrcode"><i class="icon icon-download-alt icon-white"></i> download</a> 

Mam problem, Korzystam macosx FF, Chrome i Opera Safari, a następnie nazywam saveAsPNG() metoda za pomocą elementu kliknij

obraz zwraca dokument bez rozszerzenia mają być zapisane:

data:image/octet-stream;base64,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 

Chciałbym zapisać go jako obraz, chciałby PNG/

to możliwe?

bo i ja mogę to naprawić za pomocą danych: image/png; itp .. ale otworzy się nowe okno w przeglądarce.

+1

Jeśli nie podasz prawidłowego typu MIME, w jaki sposób powinien on wiedzieć, jaki typ pliku obrazu zapisać jako? – Barmar

+0

@Barmar i jak to dodać? – sbaaaang

+0

mam na myśli, jeśli zrobię image/png otwiera się nowe okno, podczas gdy image/oktet-stream nie i nie chcę otwierać nowego okna – sbaaaang

Odpowiedz

9

W oparciu o to pytanie: Name a PNG file saved from Canvas using an "open with" dialog, można użyć atrybutu elementu adownload aby wskazać, że href należy pobrać z podanej nazwie.

Jeszcze lepiej, możemy ustawić href do wartości zwracanej toDataURL który zapewni obraz jest faktycznie pobranego jako PNG.

<a class="btn btn-large btn-inverse" id="download-qrcode" download="my_file.png"> 
    <i class="icon icon-download-alt icon-white"></i> 
    download 
</a> 

$("#download-qrcode").on('click',function(){ 
    var dataUrl = oCanvas[0].toDataURL(); 
    $(this).attr('href', dataUrl); 
}); 

Po kliknięciu linku, plik zostanie pobrany jako my_file.png. Jak stwierdzono w tym pytaniu, atrybut download nie jest tak szeroko obsługiwany - powyższy kod działał tylko w przeglądarce Chrome, mimo że Firefox najwyraźniej obsługuje ten atrybut.

Nie jestem do końca pewien, jak to obejść, ponieważ nie można ustawić adresu URL Content-Disposition w adresie URL, co oznacza, że ​​nie można wymuszać pobierania, jak to możliwe, po stronie serwera. Można również sprawdzić to: http://www.joeltrost.com/blog/2012/01/29/html5-canvas-save-a-jpeg-with-extension/. Zaletą jest to, że wymaga od serwera określania Content-Disposition, aby można było wymusić pobranie obrazu.

Edit:

Więc idea podejścia po tylnej jest po prostu wysłać Url dane z powrotem do serwera, który zasadniczo Echos go z powrotem. Sztuczka polega na tym, że ustawia się Content-Disposition, zmuszając obraz do pobrania.

Teraz link pokazuje rozwiązanie w PHP, więc prawdopodobnie można ponownie użyć skryptu, aby zrobić to samo.

+0

nie pochwycony w ogóle, przepraszam, czy href attr pozwala mi pobrać plik jako obraz? lub sugerujesz wywołanie ajax'a, aby pobrać obraz? – sbaaaang

+0

za pomocą kodu, klikając, aby pobrać przeglądarkę otworzyć nową kartę pokazującą obraz w formacie PNG, co jest dość dużym krokiem w przód, czy muszę użyć wywołania ajax do tego adresu URL, aby móc odebrać plik do pobrania? – sbaaaang

+0

to znaczy, mogę wysłać żądanie xhr wysyłając kod img base64 do małego skryptu php, że to (może) zapisuje img i sprawia, że ​​pobieram to ... – sbaaaang

Powiązane problemy