티스토리 뷰

반응형

[nextjs/typescript] 파일업로드 구현(backend/frontend)

 

#필요 라이브러리

multer

next-connect

axios

 

#라이브러리 설치

$npm i axios multer next-connect

os

# pages/api/upload/index.tsx

- config:bodyParser를 false로 지정함으로써 stream을 허용한다.

- next-connect를 활용하여, 미들웨어수준에서 file정보를 명시하여준다.

import nc from "next-connect";
import multer from "multer";
import path from "path";
import { NextApiRequest, NextApiResponse } from "next";
import { ResponseType } from "@libs/server/withHandler";


//stream 사용을 위하여 fasle 처리
export const config = {
  api: {
    bodyParser: false,
  },
};

//next-connect는 express에서 제공하는 
const handler = nc();

let storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, "public/upload");
  },
  filename: function (req, file, cb) {
    cb(
      null,
      file.fieldname + "-" + Date.now() + path.extname(file.originalname)
    );
  },
});

let upload = multer({
  storage: storage,
});

let uploadFile = upload.single("file");
handler.use(uploadFile);
handler.post(
  async (req: NextApiRequest, res: NextApiResponse<ResponseType>) => {
    console.log("req.file", req.file);
    console.log("req.body", req.body);
    let url = "http://" + req.headers.host;
    let filename = req.file.filename;
    console.log(filename);
    res.status(200).send({
      ok: true,
      result: url + "/public/" + req.file.filename,
    });
  }
);

export default handler;

 

#pages/monitoring1.tsx

-submit 이벤트 발생

-e:React.FormEvent<HTMLFormElement> 객체로 받는다.

-Formdate 객체를 생성하여, 이름을 맞춰 넣는다.

-header에 Content-Type:multipart/form-data 타입을 명시하여준다.

-onUploadProgress 이벤트를 등록하여 현재 %이벤트를 받아온다.

import type { NextPage } from "next";
import React, { useState } from "react";
import axios from "axios";
const Monitoring1: NextPage = () => {
  const [pValue, setpValue] = useState(0);
  const [file, setFile] = useState();
  const [uploadedFile, setUploadedFile] = useState({});

  const onChange = (e: React.FormEvent<HTMLInputElement>) => {
    setFile(e.target.files[0]);
    console.log(e.target.files[0].name);
  };

  const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    console.log(file);
    const formData = new FormData();
    formData.append("file", file);
    formData.append("data", { name: "gofogo" });

    try {
      const res = await axios.post("/api/upload", formData, {
        headers: {
          "Content-Type": "multipart/form-data",
        },
        onUploadProgress: (progressEvent: any) => {
          let pert = (progressEvent.loaded * 100) / progressEvent.total;
          console.log(pert);
          setpValue(pert / 100);
        },
      });
      console.log(res.data);
      const { ok, result } = res.data;

      setUploadedFile({ ok, result });
    } catch (err) {}
  };

  return (
    <div>
      <form onSubmit={onSubmit}>
        <input type="file" onChange={onChange} />
        <input type="submit" value="upload" />
      </form>
      <progress value={pValue} />
    </div>
  );
};

export default Monitoring1;

#react #nextjs #typescript #upload #file #stream #axios #multer #next-connect #api

반응형
댓글
반응형