Skip to content

CHICPRO

  • Life Log
  • Cycling Log
  • Photo Log
    • Portrait
    • Landscape
    • Flower
    • Etc
  • Coding Log
  • Information

[nodejs] 리모트 파일을 S3로 업로드 하기

2021-06-03 by 편리

nodejs 를 이용해 S3 파일 업로드는 성공했기 때문에.. nodejs 에 대해서 좀 더 심도있게 학습을 해야함에도 불구하고.. 일단은 원래 목적이었던 리모트의 파일을 S3로 업로드하는 것을 테스트 했다. 리모트의 파일을 다운로드해서 S3로 업로드 하는 것이 뭐가 어려운가.. 라고 생각할 수 있지만 이번 테스트의 목적은 로컬에 파일을 다운로드 하지 않고 바로 S3로 업로드하는 것이라서 처리가 가능할까 라는 생각이 먼저 들었다. lambda 에서 사용하기 위한 것이라서 로컬 다운로드는 생각조차 안했다.

다행히 aws-sdk 에서 stream 타입을 지원해서 가능할 것 같았다. 다운로드 하면서 바로 S3에 파일을 쓰면 간단하네.. 라고 생각할 수 있지만.. 근데 nodejs 를 제대로 모르면 이것도 생각처럼 간단하지도.. 쉽지도 않은 것이다. 물론 이걸 쉽게 처리하는 고수분들은 분명히 존재할 것이다. 나는 모르는…

우선은 파일 다운로드부터 해결을 해야했다. 다운로드는 axios 를 사용하기로 했다. 왜냐면.. 요즘 핫하니까! 그리고 부가적으로 시간처리를 쉽게 하기 위해서 moment 도 사용한다. 역시나 dotenv 와 aws-sdk 는 기본 사용이다. 구현 목표는 여러 개의 리모트 파일을 비동기로 S3로 다운로드하는 것이다. 그리고 모든 비동기 다운로드가 끝났을 때 이를 알 수 있도록 하는 방법을 제공하는 것이다.

먼저 env.js 파일과 .env 파일의 내용은 아래와 같다.

import dotenv from "dotenv";

dotenv.config();
AWS_ACCESS_KEY=
AWS_SECRET_KEY=
AWS_REGION=
AWS_BUCKET=
AWS_BUCKET_DIR=

package.json 파일의 내용은 아래와 같다.

{
  "type": "module",
  "dependencies": {
    "aws-sdk": "^2.914.0",
    "axios": "^0.21.1",
    "dotenv": "^10.0.0",
    "moment": "^2.29.1"
  }
}

모든 다운로드가 끝났는지 체크하기 위해서는 Promise.all 을 사용해야 하는데.. 문제는 내가 Promise 라는 녀석과 친하지 않다는 것이다. 이틀 정도 공부를 했는데도 어렴풋이 이해가 될 듯 말 듯한 상태라고나 할까? 순차적으로 실행되는 것만 하다보니 비동기처리는.. 역시나 쉽지가 않았다. 그래도 어쨌든 이틀 정도 코드 작성과 테스트를 반복해서 원하는 대로 기능을 하는 download.js 파일을 아래와 같이 작성했다.

import "./env.js";
import Axios from "axios";
import AWS from "aws-sdk";
import stream from "stream";
import moment from "moment";

const s3 = new AWS.S3({
  accessKeyId: process.env.AWS_ACCESS_KEY,
  secretAccessKey: process.env.AWS_SECRET_KEY,
  region: process.env.AWS_REGION
});

const uploadStream = (key) => {
  var pass = new stream.PassThrough();

  var params = {Bucket: process.env.AWS_BUCKET, Key: key, Body: pass};
  return {
    writeStream: pass,
    promise: s3.upload(params).promise()
  };
}

async function download(item) {
  console.log("[" + moment().format('YYYY-MM-DD HH:mm:ss') + "] " + item.name + " download start");

  var url = item.url;
  var dest = process.env.AWS_BUCKET_DIR + "/" + item.name;

  const {writeStream, promise} = uploadStream(dest);

  const response = await Axios({
    url,
    method: 'GET',
    responseType: 'stream'
  });

  response.data.pipe(writeStream);

  await promise;

  return new Promise((resolve, reject) => {
    promise.then(() => {
      console.log("[" + moment().format('YYYY-MM-DD HH:mm:ss') + "] " + item.name + " upload completed");
      resolve(item.name + ' upload completed');
    }).catch((err) => {
      console.log(item.name + ' upload failed.', error.message);
      reject(err.message);
    });
  });
}

function finish(resolve, reject)
{
  console.log("finished");
}

var urls = [
  {url: "https://daouoffice.com/cloud_guide/etc/daouoffice_member.pdf", name: "daouoffice_member.pdf"},
  {url: "https://trek.scene7.com/is/content/TrekBicycleProducts/Asset%20Library/documents/Manuals/pdf/RS17_MISC_Domane_Assembly_Manual_KO.pdf", name: "RS17_MISC_Domane_Assembly_Manual_KO.pdf"}
];

Promise.all(urls.map(download)).then(finish);

오류가 없는 상태에서는 정상 작동하지만 리모트 파일이 존재하지 않거나 서버가 다운되었거나 하는 등의 오류 상황에서는 아마도 제대로 작동하지 않을 수도 있다. 그런 처리까지 넣기에는 내 실력이 너무도 부족하다.

참고자료
– https://stackoverflow.com/questions/37336050/pipe-a-stream-to-s3-upload
– https://stackoverflow.com/questions/43127835/how-to-wait-for-all-async-tasks-to-finish-in-node-js

Post navigation

Previous Post:

[nodejs] AWS S3 파일 업로드

Next Post:

[nodejs] S3 내의 파일을 zip 압축하기

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Recent Posts

  • php 배열 연산에서 + 와 array_merge 의 차이
  • pcntl_fork 를 이용한 다중 프로세스 실행
  • 아이폰 단축어를 이용하여 주중 공휴일엔 알람 울리지 않게 하기
  • 구글 캘린더 전체일정 재동기화
  • OpenLiteSpeed 웹서버에 HTTP 인증 적용
  • OpenLiteSpeed 웹어드민 도메인 연결
  • WireGuard를 이용한 VPN 환경 구축
  • Ubuntu 22.04 서버에 OpenLiteSpeed 웹서버 세팅
  • 맥 vim 세팅
  • 우분투 시스템 터미널쉘 zsh 로 변경

Recent Comments

  • 편리 on 업무관리용 그누보드 게시판 스킨
  • 임종섭 on 업무관리용 그누보드 게시판 스킨
  • 캐논 5D 펌웨어 | Dslr 펌웨어 업그레이드 방법 82 개의 베스트 답변 on 캐논 EOS 30D 펌웨어 Ver 1.0.6 , EOS 5D 펌웨어 Ver 1.1.1
  • Top 5 캐논 5D 펌웨어 Top 89 Best Answers on 캐논 EOS 30D 펌웨어 Ver 1.0.6 , EOS 5D 펌웨어 Ver 1.1.1
  • 편리 on 워드프레스 애니메이션 gif 파일을 mp4로 변환하여 출력하기
  • 임팀장 on 워드프레스 애니메이션 gif 파일을 mp4로 변환하여 출력하기
  • 편리 on Notepad++ NppFTP 플러그인 수동 설치
  • paul-j on Notepad++ NppFTP 플러그인 수동 설치
  • YS on Windows 10 iCloud 사진 저장 폴더 변경
  • 편리 on Docker를 이용한 Centos7 + httpd + php 5.4 개발환경 구축

Meta

  • Log in
  • Entries feed
  • Comments feed
  • WordPress.org
© 2025 CHICPRO | Built using WordPress and SuperbThemes