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

**URL:** <https://ask.selectfromuser.com/t/s3-presigned-url/201>\
**Category:** 사용 팁\
**Tags:** s3, upload\
**Created:** [6월 20, 2024, 7:00오전 UTC](https://ask.selectfromuser.com/t/s3-presigned-url/201 "2024-06-20T07:00:49Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![hbkim](https://yyz2.discourse-cdn.com/flex032/user_avatar/ask.selectfromuser.com/hbkim/32/23_2.png) [@hbkim](https://ask.selectfromuser.com/u/hbkim)\
**Post date:** [6월 20, 2024, 7:00오전 UTC](https://ask.selectfromuser.com/t/s3-presigned-url/201/1 "2024-06-20T07:00:49Z")

</div>

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

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

```yaml
params:
- key: file
  format: file
  id: thumbnail
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 가져오기**

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

```

- `generate-presigned-url`은 presigned URL을 생성해주는 API 엔드포인트입니다.
- `fetch`를 사용해 GET 요청을 보냅니다.
- 서버가 presigned URL과 필요한 필드들을 응답으로 제공합니다.

* * *

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

```javascript
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. **파일 선택 및 준비**

```javascript
const file = document.querySelector('#thumbnail').files[0];
console.log('Uploading file:', file);

```

- 사용자가 업로드할 파일을 선택해야 합니다.
- `#thumbnail`는 HTML `<input type="file" id="thumb">`와 연결된 파일 입력 요소입니다. (params에 `id: thumbnail`)
- 선택된 파일 객체(`file`)를 준비합니다.

* * *

### 4. **폼 데이터 구성**

```javascript
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. **파일 업로드**

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

```

- presigned URL로 `POST` 요청을 보내 파일을 업로드합니다.
- 요청 본문에 `formData`를 포함합니다.

* * *

### 6. **응답 처리**

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

```

- 업로드 요청 결과를 확인합니다.
- 성공 시 "File uploaded successfully"를 로그로 출력합니다.
- 실패 시 에러 메시지를 출력합니다.

* * *

### 7. **에러 처리**

```javascript
} 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가 잘 동작하는지 확인해야 합니다.

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