saveFileDialog(blob) // light theme

Gray background. Преобразование canvas в blob для отсылки на сервер в бинарном виде (а не dataURL) или для сохранения в файл на клиенте Диалог сохранения blob на клиенте

by denvdmj

HTML

<h1>Диалог сохранения blob`а</h1>
<ul>
  <li>Преобразование canvas в blob для отсылки на сервер в бинарном виде (а не dataURL) или для сохранения в файл на клиенте </li>
  <li>Диалог сохранения blob на клиенте</li>
  <li> <a href="http://jsfiddle.net/DenVdmj/go2vpknb/">saveFileDialog(blob)</a></li>
</ul>
<div>
<input id="file-name" type="text" value="generated-image.png" />
<br />
<button id="save-dialog">Сохранить изображение на диск</button>
</div>

CSS

body {
  background: #EEE;
  color: #222;
  font: 12px/130% "Verdana";
  min-width: 20em;
  margin: auto;
  padding: 1em 4em;
}
h1, h2, h3, h4, h5, h6 {
  font: 1.5em/110% Verdana;
}
body > ul + div {
  margin: 0 0 2em 0;
}
canvas {
  border: 6px ridge #BFB;
}
img {
  border: 6px ridge #BBF;
}
button, input {
  box-sizing: border-box;
  margin: .5em 0;
  padding: .6em .6em;
  width: 20em;
  box-shadow: 0 0 2em #bbb;    
}
input {
  border: none;
  border-radius: .3em;
  background: linear-gradient(#ddd, #fff, #fff);
}
button {
  border: 0;
  outline: 0;
  border-radius: .3em;
  background: linear-gradient(#fff, #ccc);
}
button:active {
  margin: .6em -.1em .4em .1em;
  box-shadow: 0 0 .2em #444;
  background: linear-gradient(#fff, #bbb);
}

JavaScript

document.querySelector('button#save-dialog').onclick = function buttonSaveOnClick() {
  var filename = document.querySelector('input#file-name').value;
  document.querySelector('canvas').toBlob(function (blob) {
    saveFileDialog(blob, filename);
  });
};

function saveFileDialog (blob, filename, mimetype) {
  if (navigator.msSaveBlob) {
    navigator.msSaveBlob(blob, filename);
    return;
  }
  var a = document.createElement('a'),
      URL = window.URL,
      objectURL;
  if (mimetype) {
    a.type = mimetype;
  }
  a.download = filename;
  a.href = objectURL = window.URL.createObjectURL(blob);
  a.dispatchEvent(new MouseEvent('click'));
  setTimeout(URL.revokeObjectURL.bind(URL, objectURL), 500);
}


function createCanvasImage() {
  var canvas = document.createElement('canvas');
  var context = canvas.getContext('2d');
  canvas.width = 200;
  canvas.height = 150;
  context.fillStyle = '#009';
  canvas.getContext('2d').fillRect(5, 5, 190, 140);
  context.font = '16pt Arial';
  context.fillStyle = '#fff';
  context.fillText('hello, world.', 12, 40);
  document.body.appendChild(canvas);
  return canvas;
}

function testImageBlob(canvas) {
  canvas.toBlob(function (blob) {
    // проверка, что блоб правильный
    var fr = new FileReader();
    fr.onload = function () {
      var img = new Image();
      img.src = fr.result;
      document.body.appendChild(img);
    };
    fr.readAsDataURL(blob);
  });
}

if (window.HTMLCanvasElement && !HTMLCanvasElement.prototype.toBlob) {
  HTMLCanvasElement.prototype.toBlob = function (cback) {
    var str = this.toDataURL();
    str = atob(str.substr(str.indexOf('base64') + 7));
    var buffer = new ArrayBuffer(str.length);
    var bytes = new Uint8Array(buffer);
    for (var i = 0; i < str.length; ++i) {
      bytes[i] = str.charCodeAt(i);
    }
    cback(new Blob([bytes]));
  };
}

testImageBlob(createCanvasImage());