개인프로젝트

[팁] NODEJS 그리고 AWS S3 버킷생성, 파일 업로드, 파일 다운로드 기능 한번에 구현하기 - 소스코드 포함

티멀 2024. 5. 9. 16:48
728x90
반응형

소스코드

이번에 S3 처음 써보면서 NODE에 접목시키는 것에 조금 뻘짓을 좀 많이했습니다.

저같은 사람이 없길 바라며 정리해보는 글.

 

위에서부터 하나씩 순서대로 복붙해가면 끝이에요.

편하게 개발 고!

 

버킷 생성자

createBucket.js

const path = require("path");
// 이건 단순 ENV 파일 설정. 여러분 ENV 파일 맞춰서 설정해주세요
require("dotenv").config({
  path: path.resolve(
    __dirname,
    "..",
    "env",
    process.env.NODE_ENV === "production" ? ".env.prod" : ".env.dev"
  ),
});

const AWS = require("aws-sdk");
const ACCESS_KEY = process.env.ACCESS_KEY;
const SECRET_KEY = process.env.SECRET_KEY;
const BUCKET_NAME = process.env.BUCKET_NAME;
const s3 = new AWS.S3({ accessKeyId: ACCESS_KEY, secretAccessKey: SECRET_KEY });
const params = {
  Bucket: BUCKET_NAME,
  CreateBucketConfiguration: {
    // Set your region here
    LocationConstraint: process.env.LocationConstraint,
  },
};

module.exports = s3;

 

파일 업로드

uploadFile.js

const fs = require("fs");
const path = require("path");
require("dotenv").config({
  path: path.resolve(
    __dirname,
    "..",
    "env",
    process.env.NODE_ENV === "production" ? ".env.prod" : ".env.dev"
  ),
});

const uploadFile = (s3, file, fileName) => {
  const params = {
    Bucket: process.env.BUCKET_NAME,
    Key: fileName, // File name you want to save as in S3
    Body: file,
    // ContentType: "image/png"
  };
  s3.upload(params, function (err, data) {
    if (err) {
      throw err;
    }
    // console.log(`File uploaded successfully. ${data.Location}`);
  });
};

module.exports = uploadFile;
// uploadFile(s3, './assets/test.png', 'testupded.png')

 

 

파일 다운로드

여기서 파일을 다운로드 받을 때 저는 db에 저장된 유니크 값을 가지고 파일을 조회한 후 지정한 파일 이름으로 다운받게 코드를 짜놨습니다.

 

더 효율적인 방법 있으면 댓글좀 ㄳㄳ

 

downloadFile.js

const path = require("path");
require("dotenv").config({
  path: path.resolve(
    __dirname,
    "..",
    "env",
    process.env.NODE_ENV === "production" ? ".env.prod" : ".env.dev"
  ),
});
const downloadFile = (s3, dbFileName, downloadFileName, res) => {
  const params = {
    Bucket: process.env.BUCKET_NAME,
    Key: dbFileName, // File name you want to save as in S3,
    // Expires: 3600, // URL expires in 1 hour (adjust as needed)
  };

  s3.getObject(params, (err, data) => {
    if (err) {
      console.error(err);
      return res.status(500).send("Error downloading file");
    }

    res.set({
      "Content-Disposition": `attachment; filename="${downloadFileName}"`,
      "Content-Type": data.ContentType,
    });
    res.send(data.Body);
  });
};
module.exports = downloadFile;
// downloadFile("../../uploads/test-download.txt");

 

사용법

 

node 서버 내 선언

server.js OR index.js (여러분의 서버 index)

const s3 = require("../config/createBucket");

 

 

이제 여러분의 파일을 react에서 받아온다고 가정할 때, react는 아래처럼 blob으로 바꿔줍니다.

const uploadFileHandler = async (file, orderNum, version) => {
    // 이 블롭이 point!
    const blob = new Blob([file.originFileObj], { type: file.type });
    const response = await axios.post(
      `${process.env.REACT_APP_BACKEND_ROOT}/file/save/${file.name}/no/${orderNum}/ver/${version}`,
      blob,
      {
        headers: {
          "Content-Type": file.type,
        },
      }
    );

    console.log("response", response);
    return response.data;

 

 

그리고 node에 파일 사이즈 limit이 걸려있으니까 아래 코드 넣어서 조절해줍시다.

app.use(
  express.json({
    limit: "500mb",
  })
);
app.use(
  express.urlencoded({
    limit: "500mb",
    extended: false,
  })
);

app.use(bodyParser.raw({ type: "*/*", limit: "500mb" }));

 

 

받은 blob파일은 아래 node 통해서 업로드하면 됩니다.

router.post("/save/:fileName/no/:orderNum/ver/:version", async (req, res) => {
  try {
    const fileBuffer = Buffer.from(req.body);
    uploadFile(s3, fileBuffer, 'S3에 저장할 파일 이름');
    res.status(200).json(true);
  } catch (error) {
    console.log("er", error);
    logger.error("error", error);
    res.status(500).json({ error: error });
  }
});

 


이젠 다운로드!

 

노드쪽에서는

router.post("/download", async (req, res) => {
  const { fileName, fileDBName } = req.body;
  // fileName은 다운로드 받고 난 후 저장할 파일이름이고
  // fileDBName은 현재 S3에 저장된 실제 파일이름이여야함 -> OBJECT KEY값이라고 보면 됨
  downloadFile(s3, fileDBName, fileName, res);
});

 

 

REACT쪽에서는

이렇게 요청하면 끝입니다!

  const downloadFile = async (fileName, fileDBName) => {
    const data = { fileName: fileName, fileDBName: fileDBName };
    const response = await axios.post(
      `${process.env.REACT_APP_BACKEND_ROOT}/file`,
      data,
      { responseType: "blob" }
    );

    const url = window.URL.createObjectURL(response.data);
    // Create an <a> element to trigger the download
    const a = document.createElement("a");
    a.href = url;
    a.download = fileName;
    document.body.appendChild(a);
    a.click();
    window.URL.revokeObjectURL(url);
  };

 


 

참, 이거 만들려고 한 3시간은 뻘짓한거 같은데, 여러분은 좀 편하게 개발하면 좋으실 것 같아서 올려봐요!

 

즐코딩

728x90
반응형