선택된 파일들 s3 presigned url 발급후 업로드하는 방법

presignedUrl 를 통해 자체 S3 버킷에 이미지를 업로드

insert 할 때, requestSubmitFn을 통해 선택된 파일들을 s3 presigned url 발급 받아서 업로드하는 예시입니다.

requestSubmitFn: |
  try {
    const response = await fetch("generate-presigned-url", {
      method: 'GET',
      mode: 'cors'
    });

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const result = await response.json();
    const presignedData = result[0];
    const url = presignedData.url;
    const fields = presignedData.fields;

    // 업로드할 파일
    const file = document.querySelector('#thumbnail').files[0];
    console.log('Uploading file:', file);

    const formData = new FormData();
    formData.append('key', fields.key);
    formData.append('acl', fields.acl);
    formData.append('bucket', fields.bucket);
    formData.append('X-Amz-Algorithm', fields['X-Amz-Algorithm']);
    formData.append('X-Amz-Credential', fields['X-Amz-Credential']);
    formData.append('X-Amz-Date', fields['X-Amz-Date']);
    formData.append('Policy', fields.Policy);
    formData.append('X-Amz-Signature', fields['X-Amz-Signature']);
    formData.append('Content-Type', file.type);  // 파일의 MIME 타입
    formData.append('file', file);

    const uploadResponse = await fetch(url, {
      method: 'POST',
      body: formData
    });

    if (uploadResponse.ok) {
      console.log('File uploaded successfully');
    } else {
      console.error('File upload failed', uploadResponse.statusText);
    }

  } catch (error) {
    console.error('Failed to fetch presigned URL:', error);
  }

위 코드는 JavaScript를 사용하여 파일을 업로드하는 비동기 요청 함수입니다. 주로 AWS S3와 같은 스토리지 서비스에 파일을 업로드할 때 활용됩니다. 다음은 코드의 주요 흐름과 작동 방식을 설명합니다:


1. Presigned URL 가져오기

const response = await fetch("generate-presigned-url", {
  method: 'GET',
  mode: 'cors'
});
  • generate-presigned-url은 presigned URL을 생성해주는 API 엔드포인트입니다.
  • fetch를 사용해 GET 요청을 보냅니다.
  • 서버가 presigned URL과 필요한 필드들을 응답으로 제공합니다.

2. Presigned URL 유효성 검사 및 데이터 추출

if (!response.ok) {
  throw new Error(`HTTP error! status: ${response.status}`);
}
const result = await response.json();
const presignedData = result[0];
const url = presignedData.url;
const fields = presignedData.fields;
  • 응답이 성공(200 OK)인지 확인하고, JSON 데이터를 추출합니다.
  • presignedData는 파일 업로드에 필요한 URL 및 필드 데이터를 포함합니다:
    • url: 파일을 업로드할 대상 URL.
    • fields: 업로드 요청 시 필요한 필드 데이터(예: 인증 정보, 정책 등).

3. 파일 선택 및 준비

const file = document.querySelector('#thumbnail').files[0];
console.log('Uploading file:', file);
  • 사용자가 업로드할 파일을 선택해야 합니다.
  • #thumbnail는 HTML <input type="file" id="thumb">와 연결된 파일 입력 요소입니다. (params에 id: thumbnail)
  • 선택된 파일 객체(file)를 준비합니다.

4. 폼 데이터 구성

const formData = new FormData();
formData.append('key', fields.key);
formData.append('acl', fields.acl);
formData.append('bucket', fields.bucket);
formData.append('X-Amz-Algorithm', fields['X-Amz-Algorithm']);
formData.append('X-Amz-Credential', fields['X-Amz-Credential']);
formData.append('X-Amz-Date', fields['X-Amz-Date']);
formData.append('Policy', fields.Policy);
formData.append('X-Amz-Signature', fields['X-Amz-Signature']);
formData.append('Content-Type', file.type);  // 파일의 MIME 타입
formData.append('file', file);
  • FormData 객체를 생성하고 필요한 데이터를 추가합니다.
  • fields에 포함된 인증 및 정책 정보를 폼 데이터에 추가합니다.
  • 업로드할 파일(file)도 포함합니다.

5. 파일 업로드

const uploadResponse = await fetch(url, {
  method: 'POST',
  body: formData
});
  • presigned URL로 POST 요청을 보내 파일을 업로드합니다.
  • 요청 본문에 formData를 포함합니다.

6. 응답 처리

if (uploadResponse.ok) {
  console.log('File uploaded successfully');
} else {
  console.error('File upload failed', uploadResponse.statusText);
}
  • 업로드 요청 결과를 확인합니다.
  • 성공 시 "File uploaded successfully"를 로그로 출력합니다.
  • 실패 시 에러 메시지를 출력합니다.

7. 에러 처리

} catch (error) {
  console.error('Failed to fetch presigned URL:', error);
}
  • presigned URL 요청 또는 업로드 중 에러가 발생할 경우 적절히 처리합니다.

요약

이 코드는 다음과 같은 상황에서 유용합니다:

  1. Presigned URL 기반 파일 업로드: AWS S3와 같은 스토리지 서비스에 안전하게 파일을 업로드하기 위해 사용.
  2. 보안 강화: 파일 업로드에 필요한 인증 데이터를 포함한 presigned URL을 사전에 생성해 서버 측에서 관리.
  3. 사용자 경험 개선: 비동기로 처리되어 사용자 인터페이스가 멈추지 않음.

추가적으로, #thumbnail에 올바른 파일 입력 요소를 연결하고, presigned URL을 제공하는 서버 API가 잘 동작하는지 확인해야 합니다.

관련하여 도움이 필요하시다면 문의해주세요.
감사합니다.