콘텐츠로 이동

파일 업로드 (PUT)

파일을 R2 스토리지에 업로드합니다. 파일 크기에 따라 자동으로 단일 업로드 또는 스트리밍 멀티파트 업로드로 분기됩니다.

요청

PUT https://r2-worker.construcion24.workers.dev/{path}
Authorization: Bearer <token>

요청 형식

=== "multipart/form-data"

```
Content-Type: multipart/form-data

file: (바이너리 파일 데이터)
```

`file` 필드에 파일을 첨부합니다.

=== "application/octet-stream"

```
Content-Type: application/octet-stream
X-Filename: document.pdf

(바이너리 파일 데이터)
```

요청 body에 파일을 직접 포함하고, `X-Filename` 헤더로 파일명을 전달합니다.

업로드 자동 분기

파일 크기 방식 설명
10MB 미만 단일 업로드 파일을 메모리에 로드 후 한 번에 업로드
10MB 이상 스트리밍 멀티파트 업로드 파일을 10MB 청크 단위로 스트리밍 업로드

5단계 검증 (단일 업로드)

업로드 전 다음 검증을 순서대로 수행합니다.

단계 검증 항목 실패 시
1 HTTP 메서드 - 토큰의 method와 요청 메서드 일치 400 "HTTP 메서드 검증 실패"
2 파일 데이터 존재 - 파일이 비어있지 않은지 400 "요청에 파일 데이터가 없습니다"
3 파일명 - 토큰의 originalFilename과 일치 400 "파일명 검증 실패"
4 MIME 타입 - 토큰의 meta.mime과 일치 (설정된 경우) 400 "MIME 타입 검증 실패"
5 파일 크기 - 토큰의 meta.size와 오차 범위 내 (설정된 경우) 400 "파일 크기 검증 실패"

파일 크기 검증 오차 허용

허용 오차 = max(1KB, 예상 크기 × 1%)

  • 절대 오차: 1,024 바이트 (1KB)
  • 상대 오차: 예상 크기의 1%
  • 두 값 중 큰 쪽을 허용 범위로 사용

멀티파트 업로드 (10MB 이상)

멀티파트 업로드 시에는 파일을 메모리에 올리지 않고 스트리밍으로 처리합니다.

사전 검증

  • HTTP 메서드 검증
  • 파일명 검증
  • MIME 타입 검증

스트리밍 처리

  1. R2 멀티파트 업로드 세션 생성
  2. ReadableStream에서 데이터를 읽으며 10MB 단위로 파트 업로드
  3. 마지막 파트는 5MB 미만 허용 (R2 최소 요구사항)
  4. 모든 파트 업로드 완료 후 병합

사후 검증

  • 스트리밍 완료 후 전체 파일 크기를 토큰의 meta.size와 비교
  • 검증 실패 시 업로드된 파일을 R2에서 즉시 삭제

에러 발생 시

멀티파트 업로드 도중 에러가 발생하면 multipart.abort()를 호출하여 불완전한 파트를 정리합니다.

Firebase 알림 및 롤백

업로드 성공 후 Firebase Cloud Function에 메타데이터를 전송합니다.

Firebase 페이로드

{
  "path": "companies/...",
  "company_id": "comp_123",
  "related_doc_id": "doc_456",
  "site_id": "site_789",
  "doc_type": "contract",
  "doc_page": "1",
  "tags": {},
  "filename": "document.pdf",
  "target_date": "2024-01-01",
  "size": 5242880,
  "mime": "application/pdf",
  "uid": "user_id"
}

롤백 메커니즘

Firebase 알림이 실패하면 보상 트랜잭션(Compensating Transaction) 패턴을 적용합니다.

  1. Firebase 알림 실패 감지
  2. R2에서 방금 업로드한 파일 삭제
  3. 에러 응답 반환

응답

성공 (200)

모든 검증 통과 및 파일 업로드 완료!

Token is valid for key "companies/..."
...

멀티파트 업로드 시:

모든 검증 통과 및 파일 업로드 완료! (멀티파트)

Token is valid for key "companies/..."
...

에러

HTTP 상태 메시지 원인
400 HTTP 메서드 검증 실패 토큰 method와 불일치
400 요청에 파일 데이터가 없습니다 파일 누락 또는 크기 0
400 파일명 검증 실패 파일명 불일치
400 MIME 타입 검증 실패 MIME 타입 불일치
400 파일 크기 검증 실패 크기 오차 범위 초과
400 multipart/form-data에서 'file'을 찾을 수 없습니다 form-data 파싱 실패
500 R2 멀티파트 업로드 실패 R2 업로드 에러
500 Firebase 업데이트 실패 (R2 롤백 완료) Firebase 응답 실패
500 Firebase 연결 실패 (R2 롤백 완료) Firebase 연결 에러