프로젝트 중 버튼을 누르면
1. canvas 데이터 생성
2. canvas데이터 blob파일로 변환
3. form data에 담아서 axios 요청으로 보내기
사진파일 생성과 동시에 게시글이 작성되는 로직을 구현하고 싶었다
var file = new Blob([new ArrayBuffer(array)], {type: 'image/png'});
위와 같이 MIME type을 설정을 해주면 된다고 생각했다.
하지만 backend(springboot)로 POST 요청 후, DB를 확인해보면
사진과 같이 .blob
url로 저장이 되었다.
비록 프로젝트기간에는 해결하지 못하고 a태그를 사용하여
사진 파일을 다운 받고 수동으로 다시 게시글을 업로드 하는 로직으로 대체하였지만...
.png
로 저장이 되도록 하는 목표를 가지고 다시 시도!
const newBlob = new Blob([typedArray], options);
Blob 생성자의 첫번째 인수(typedArray)로
ArrayBuffer
, ArrayBufferView
, Blob(File)
, USVString(DOMString) 객체
또는 이러한 객체가 혼합된 Array
를 사용할 수 있다.
USVString은 UTF-8로 인코딩된다.
new Blob([new ArrayBuffer(data)], { type: 'video/mp4' });
new Blob(new Uint8Array(data), { type: 'image/png' });
new Blob(['<div>Hello Blob!</div>'], {
type: 'text/html',
endings: 'native'
});
옵션으로는 type
과 endings
를 설정 가능
type
데이터의 MIME 타입
을 설정
기본값은 ""
endings
데이터가 텍스트일 때, 개행 문자(\n
)를 어떻게 해석할지 지정
"transparent"
와 "native"
로 지정할 수 있음
기본값은 "transparent"
var blob = new Blob([typedArray], {type: 'application/octet-binary'});
const obj = {hello: 'world'};
const blob = new Blob([JSON.stringify(obj, null, 2)], {type : 'application/json'});
MIME(Multipurpose Internet Mail Extension)
예전에는 ACII로 공통 표준따르기만하면 됐지만, 점차 음악 등 binary 파일을 보내야 하는 경우가 생겼고 ASCII로는 전송이 불가능하게 됨
-> 텍스트 파일로의 변환 필요
-> 즉, MIME는 새로운 인코딩 방식
Encoding
: binary -> text
Decoding
: text -> binary
MIME type
이란 클라이언트에게 전송된 문서의 다양성을 알려주기 위한 메커니즘
(웹에서 파일의 확장자는 별 의미가 없다 -> 각 문서와 함께 올바른 MIME 타입을 전송하도록, 서버가 정확히 설정하는 것이 중요)
브라우저들은 리소스를 내려받았을 때 해야 할 기본 동작이 무엇인지를 결정하기 위해 대게 MIME 타입을 사용
canvas 데이터 png 파일로 다운받는 로직
1. canvas 데이터 그리기
2.<a>
태그를 사용하여 다운로드
draw() {
var canvas = document.getElementById("canvas");
if (canvas.getContext) {
var ctx = canvas.getContext("2d");
ctx.font = "20px serif";
ctx.fillStyle = "rgb(204,229,255)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "rgb(0,0,0)";
ctx.fillText("Hello", 20, 30);
}
this.saveImage();
},
saveImage() {
var link = document.createElement("a");
link.download = "hello.png";
link.href = document.getElementById("canvas").toDataURL("image/png");
link.click();
},
canvas.toDataURL(type, encoderOptions);
data:[<type>][;base64],<data>
canvas 데이터 png 파일로 변환 후 axios 보내기
1. canvas 데이터 그리기
2.toDataURL()
로 canvas 데이터 base64 인코딩 문자열 반환
3. base 64 디코딩 -> Blob 객체 생성
4. Blob -> File로 변환
5. FormData() 형태로 axios POST
draw() {
var canvas = document.getElementById("canvas");
if (canvas.getContext) {
var ctx = canvas.getContext("2d");
ctx.font = "20px serif";
ctx.fillStyle = "rgb(204,229,255)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "rgb(0,0,0)";
ctx.fillText("Hello", 20, 30);
}
// toDataURL()사용하여 png타입의 base64인코딩된 data url 형식의 문자열을 반환
var dataUrl = canvas.toDataURL('image/png')
console.log(dataUrl)
// data:image/jpeg;base64,/9j/4AAQSkZJRg...AAAAAB//2Q==
// data : <type> <;base64> <data>
// <data> 부분 뽑아내기
// atob = ASCII -> binary
// btoa = binary -> ASCII
// base64 데이터 디코딩
var byteString = window.atob(dataUrl.split(',')[1]);
var array = [];
// i 에 해당하는 string을 unicode로 변환
for (var i = 0; i < byteString.length; i++) {
array.push(byteString.charCodeAt(i));
}
// console.log(array)
// (2486) [137, 80, 78, 71, ...]
// Blob 생성
var myBlob = new Blob([new ArrayBuffer(array)], {type: 'image/png'});
// ** Blob -> File 로 변환**
var file = new File([myBlob], "blobtofile.png");
var formData = new FormData();
formData.append("media", file);
formData.append("content", "Blob확인");
formData.append("tagList", "blob");
formData.append("username", "admin");
axios
.post("/feed/feeds", formData, {
headers: {
"Content-Type": "multipart/form-data",
Authorization: sessionStorage.getItem("jwt"),
},
})
.then((res) => {
console.log(res);
})
.catch((err) => {
alert("실패");
console.log(err)
});
},
성공적으로 DB에 저장됨을 볼 수 있다!🥳
예상하기로는 File 자체로 받도록 backend 쪽에서 처리를 한 것 같은데 이 부분 때문에 중간에 Blob을 File 객체로 다시 변환해서 전송시키는 부분이 필요했던 것 같다
덕분에 이런저런 공부가 되었다!
https://heropy.blog/2019/02/28/blob/
https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=magnking&logNo=220950061851
https://developer.mozilla.org/ko/docs/Web/API/Blob#%EB%B8%94%EB%A1%AD%EC%97%90%EC%84%9C_%EB%8D%B0%EC%9D%B4%ED%84%B0_%EC%B6%94%EC%B6%9C%ED%95%98%EA%B8%B0
https://kyounghwan01.github.io/blog/JS/JSbasic/Blob-url/#createobjecturl
http://charlie0301.blogspot.com/2014/10/html5-canvas-blob-data-post-upload.html
https://stackoverflow.com/questions/18253378/javascript-blob-upload-with-formdata
https://samanoske.tistory.com/m/94
https://taeny.dev/javascript/file-object/#1-file-%EA%B0%9D%EC%B2%B4
프론트 마스터가 되어가시네요 👀