파일 업로드 재개하기

파일 업로드 재개하기

fetch 메서드를 사용하면 파일을 업로드 할 수 있다. 용량이 큰파일을 업로드할 때 나누어서 업로드 해야하는 경우가 생기는데, 이때 사용하는 내장된 기능은 없지만 부분적으로 구현할 수 있는 여러 기능은 있다.

해당 기능을 사용하기 위해서는 업로드 진행률을 알아야 하는데 fetch 로는 업로드 진행률을 알지 못하기 때문에 XMLHttpRequest를 사용해서 알아낸다.

별 도움 안되는 진행률 이벤트

앞서서 xhr.upload.onprogress로 업로드 진행률을 알수 있다는 것을 살펴 보았다. 하지만 이는 브라우저에서 요청 보낼때 작동할 뿐이지, 서버에서 데이터를 받았을때 작동하지는 않는다.

이는 네트워크 문제나 여러가지 상황에서 서버가 리시브 받지 못했음에도 업로드 한것처럼 보일수 있는 위험이 있다. 따라서 서버에서 정확히 얼마만큼 리시브 받았는지에 대한 정보가 필요한데 이는 따로 요청을 보내서 확인해야 한다.

알고리즘

  1. 업로드할 파일에 고유값을 생성한다.
1
let fileId = file.name + "-" + file.size + "-" + file.lastModifiedDate;

파일 아이디는 파일 업로드를 재개할 때 서버에 어떤 파일을 재개할지 말해주는데 필요하다.

  1. 서버에 요청을 보내어 얼마만큼 바이트를 전송했는지 질의한다.
1
2
3
4
5
6
7
8
let response = await fetch("status", {
headers: {
"X-File-Id": fileId,
},
});

// 서버가 얼마만큼 파일 바이트를 가졌는지 확인한다.
let startByte = +(await response.text());

서버가 X-File-Id 헤더에서 파일 업로드를 추적한다고 가정한다. 이 작업은 사버사이드에서 구현되어 있어야 하고, 아직 파일이 서버에 없으면 서버는 0으로 응답해야 한다.

  1. startByte 에서 파일을 보내기 위해 Blobslice 메서드를 사용한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
xhr.open("POST", "upload", true);

// 파일 아이디를 통해 서버는 어떤 파일을 업로드 받을지 알게 된다.
xhr.setRequestHeader("X-File-Id", fileId);

// 서버는 업로드를 제개할 파일의 시작 바이트를 통해 파일 업로드가 재개될 것을 알게 된다.
xhr.setRequestHeader("X-Start-Byte", startByte);

xhr.upload.onprogress = (e) => {
console.log(`Uploaded ${startByte + e.loaded} of ${startByte + e.total}`);
};

// 업로드를 할 파일은 input.files[0]나 또 다른 출처가 될 수 있습니다.
xhr.send(file.slice(startByte));

파일 아이디인 X-File-Id를 서버로 보내 업로드를 진행할 파일이 어떤 것인지 알리고, 시작 바이트인 X-Start-Byte를 서버에 보내 파일 업로드를 초기화하지 않고 파일 업로드를 다시 시작한다는 것을 서버에 알게 한다.