resume 업로드 기능 만들기

resume 업로드란? 흔히 말하는 일시정지기능으로 업로드를 다시 시작할수 있는 기능이다
참고로 예제코드는 php

프로세스

1.파일 오픈 및 읽기

$readHandle = fopen($filePath, 'r'); $writeHandle = fopen($filePath, 'a');
두개의 파일핸들러를 만든다
하나는 읽기전용 하나는 쓰기전용
읽기는 r 모드로 오픈시 항상 포인터를 시작점에 놓기위해 주었고 a는 쓰기모드인데 파일포인터를 끝점에 놓기 위해 주었다
 

2. 쓰기

try{ $chunkSize = 8192; //한번 읽을때 8 kilobytes while(! feof($readHandle)){ $data = fread($readHandle, $chunkSize); $bytes = fwrite($writeHandle, $data, $chunkSize); } }finally{ fclose($readHandle); fclose($writeHandle); }
위와 같은 과정이 기본적인 업로드 과정이다
resume 기능을 추가하기 위해서는 알고있어야 할 정보가 있다
 
offset 정보 : 현재까지 업로드 된 bytes offset을 알고 있으면 그 이후부터 업로드를 하는 방식으로 재시작 기능을 만들 수 있으니까
 
클라이언트는 offset정보를 받아서 그 이후부터 read 작업을 통해 데이터를 서버로 쏘고
서버는 데이터를 쌓기만 하면 된다
 

Offset을 얻는 방법

  1. read 와 write를 이용한 파일시스템에다가 고유 아이디로 파일이름을 만들고 저장하는 방법
    1. 매 순간 read 와 write가 발생하기 때문에 성능적인 측면에서 매우 느려질 수 있다
  1. redis와 같은 in_memory db 사용하기
    1. 메모리에 저장하기 때문에 매우 빠른속도로 offset 업데이트가 가능하다
  1. 파일 경로에서 파일 사이즈 얻기
    1. 업로드 되고있던 파일의 정보를 가져와서 현재 bytes를 가져오면 어디까지 업로드 됬는지 알 수 있다
    2. 내가 테스트 해봤을때 문제는 없었다 다만 일시정지와 재시작을 연속적으로 눌렀을때 I/O의 대기작업이 물려있고 bytes를 가져왔을때 내가 보냈던 데이터보다 더 적은상태라서 예를 들어 클라이언트에서 1키로바이트씩 100개를 쐈는데 파일 정보를 조회 하면 아직 900키로바이트인 상황이라 파일의 정합성이 떨어질 수 있다 사용하게 된다면 체크섬 기능을 추가하는 것은 필수! 일것 클라이언트에 전달한 offset 부터 뒤로 쌓아가는 방식 대신 파일 포인터를 그 위치로 정확하게 옮겨서 사용할 것
 

쓰기(resume)

try{ $chunkSize = 8192; //한번 읽을때 8 kilobytes // 3가지 방법중 가져온 offset // 당연히 처음 일때는 0부터 해야겠지 $offset fseek($writehandle,$offset); while(! feof($readHandle)){ $data = fread($readHandle, $chunkSize); $bytes = fwrite($writeHandle, $data, $chunkSize); // write가 발생할때마다 offset을 업데이트 해준다 $offset += $bytes; } }finally{ fclose($readHandle); fclose($writeHandle); }
 

전체적인 흐름

sequenceDiagram actor A as client participant B as Server participant C as Storage A ->> B : offset 요청 B ->> A : offset 반환 ex) 20 bytes A ->> B : 파일 포인터를 20 bytes 부터 read 하여 데이터 전송 B ->> C : file write 작업
notion image
일반적인 클라이언트에서 데이터를 쏘기만 하는것과는 다르게 offset요청의 흐름을 한번 거치게 된다
 
댓글 0

등록된 댓글이 하나도 없습니다...😢