File API에서 blob나 file object를 추출하는 방법은 여러 사이트에 설명이 잘 되어 있는데 이걸로 뭘 어떻게 하는 것인지 이해가 되지 않거나 잊어버리는 때가 많아서 따로 정리해 둔다.

아래의 예제는 canvas의 내용을 BLOB형태로 추출한 후 이를 img의 src로 사용하는 케이스를 설명한다.

canvas에 원을 그린 후 이 그림을 img의 src에 적용한다. 먼저 원을 그리려면

var canvas = document.createElement('canvas');
//document.body.appendChild(canvas);

var height = 200;
var width = 200;

canvas.width = width;
canvas.height = height;

var ctx = canvas.getContext('2d');

ctx.strokeStyle = '#090';
ctx.beginPath();
ctx.arc(width / 2, height / 2, width / 2 - width / 10, 0, Math.PI * 2);
ctx.stroke();

canvas의 toBlob 함수에서 blob를 받으면 이를 바로 img의 src에 적용하는 것은 작동하지 않는다. 즉 아래 코드는 작동하지 않는다.

canvas.toBlob(function(blob) {
	document.getElementById('myimg').src = blob
});

대신 FileReader의 readAsDataURL을 쓰는 다음의 예는 작동한다.

canvas.toBlob(function(blob) {
	var reader = new FileReader();
	reader.onload = function(e) {
		document.getElementById('myimg').src = reader.result);
	}
	reader.readAsDataURL(blob);
});

또 다른 방법으로 URL object의 creatObjectURL 를 사용하는 방법이 있다.

canvas.toBlob(function(blob) {
	var url = URL.createObjectURL(blob);
	const img = document.getElementById('myimg');
	img.src = url;
	img.onload = function() {
		//cleanup.
		URL.revokeObjectURL(this.src);
	}
});
  • 첫 번째 예제는 blob를 src에 그대로 할당했다.
  • 두 번째 예제는 blob를 base64인코딩된 문자열로 표시한 것이다.
  • 세 번째 img는 URL.createObjectURL을 사용하여 url 형태로 만들어 준 뒤 src에 할당하였다.

첫 번쨰 예제에서 blob 자체를 src에 할당하면 img는 이를 이해하지 못 한다. 다른 예에서 처럼 URL형태로 만들어 주던지, data: 형식으로 표현된 base64 인코딩의 문자열을 전달하던지 해야 한다. base64 인코딩된 문자열로 변환 시켜주려면 두 번째 예제처럼 FileReader API를 사용해야 한다. 두 번쨰 예제의 img를 검사해보면 src에 data:image/png;base64,….. 이 들어있음을 알 수 있다. 세 번째 img 는 URL.createObjectURL 을 사용해서 할당한 예이며 이 예제에서 이 URL은 revoke 되었기 때문에 이미지 다운로드는 작동하지 않는다. 이와 달리 두 번째 예제는 데이터를 유지하고 있으므로 다운로드가 가능하다.