EtoC

유저 프로필 이미지 업로드 만들기 본문

BackEnd/NodeJs

유저 프로필 이미지 업로드 만들기

게리드 2023. 8. 28. 14:53

1 input 만들기

2. multer middleware 사용하기

설치: $ npm install --save multer

파일을 업로드 할수 있게 해준다. multer를 사용하기위해서는 조건이 딱 1개 있는데 form에 multipart/form-data을 formd에 입력해야한다.
multer는 multiple 이 아닌 form을 처리하지 않는다고 쓰여있다.

form(method="POST", enctype="multipart/form-data")

이것은 form이 다르게 encode 되게하는것이다.
여기서 enctype은 백엔드로 보내기위해 필요한 encoding tyoe이다..

2-1 multer middleware 만들기

공식 문서 예
const express = require('express')
const multer  = require('multer')
const upload = multer({ dest: 'uploads/' })//설정과함께 multer함수를 사용하여 middleware를 만든다

const app = express()

 

app.post('/profile', upload.single('avatar'), function (req, res, next) {
//url이 있고 그뒤에 middleware, controller함수를 쓴다.
// req.file 은 avatar 라는 필드의 파일 정보이다.
// 텍스트 필드가 있는 경우, req.body가 이를 포함한다.
})

 

app.post('/photos/upload', upload.array('photos', 12), function (req, res, next) {
// req.files 는 photos 라는 파일정보를 배열로 가지고 있습니다.
// 텍스트 필드가 있는 경우, req.body가 이를 포함할 것입니다.
})

 

const cpUpload = upload.fields([{ name: 'avatar', maxCount: 1 }, { name: 'gallery', maxCount: 8 }])
app.post('/cool-profile', cpUpload, function (req, res, next) {
// req.files는 (String -> Array) 형태의 객체 입니다.
// 필드명은 객체의 key에, 파일 정보는 배열로 value에 저장됩니다.
//
// e.g.
// req.files['avatar'][0] -> File
// req.files['gallery'] -> Array
//
// 텍스트 필드가 있는 경우, req.body가 이를 포함할 것입니다.


multer에는 configuration object(옵견 객체)가 있다.
**multer(opts)**
 기본 옵션인 dest 요소는 Multer에게 파일을 어디로 업로드 할 지를 알려준다. 
 옵션 객체를 생략했다면, 파일은 디스크가 아니라 메모리에 저장될 것이다.

기본적으로 Multer는 이름이 중복되는 것을 방지하기 위해서 파일의 이름을 재작성 하며,필요에 따라 해당 함수는 커스터마이징이 가능하다.

Multer로 전달 가능한 옵션들은 다음과 같다.

|Key|Description|
|:---:|:---:|
|dest or storage|    파일이 저장될 위치 |
|fileFilter    |어떤 파일을 허용할지 제어하는 함수|
|limits|    업로드 된 데이터의 한도|
|preservePath|    파일의 base name 대신 보존할 파일의 전체 경로|
보통의 웹 앱에서는 dest 옵션 정도만 필요할지도 모릅니다. 설정 방법은 아래의 예제에 나와있습니다.

```js
const upload = multer({ dest: 'uploads/' })
//사용자가 업로드하는 파일을  서버의 uploads폴더에 저장하게 한다.

그런데 아바타 이미지를 편집하려니까 에러가 났다.

    ReferenceError: findByIdAndUpdate is not defined //함수명 바꾸고 아래에서 이전 명으로 호출함;
    ReferenceError: uploadFiles is not defined //라우트에 써놓고 import안함;;

라우트 함수명을 쓰면 자동으로 불러와줬는데 도구에 지배되지말자..확인 또 확인!!

       avartarUrl: file ? file.path : avartarUrl,
                        ^
    ReferenceError: file is not defined

file이 정의되어있지 않다고하는데 가져온session데이터를 확인해보니 avartarUrl이 없었다.
schema에도 가져올 user데이터에도 확실히 써놓았고 upload폴더에는 사진이 저장되는데 왜 DB에 저장이 안되는걸까..

원인은 파일의 경로 문제
.

경로를수정해주니 avatarUrl이 upload폴더에 저장되고 db에 저장된것을 확인할 수 있었다.


추가로 절대 DB에는 파일을 저장하면 안되고 파일의 위치만을 저장해야한다.
DB에는 url을 저장하고, 원본 파일은 amazon의 하드드라이브 같은 곳에 저장해야한다.
dest or storage가 비추인 이유는 브라우저가 서버의 어떤 폴더로 갈수 있으면 보안상 좋지않기때문이다.
그래서 브라우저가 어떤 페이지와 폴더를 볼 수 있는지 알려줘야한다.
static file servering을 활성화 해야한다.

위 문장은 폴더를 가지고 그 폴더의 전체를 브라우저에 노출하는 것이다.

app.use("/uploads", express.static(노출하고싶은폴더명));

누군가 /uploads로 가려하면 express가 uploads폴더의 내용을 보여준다.


아잇.. 다 되는데 이미지가 안바뀐다.


개발자도구에 들어가서 확인해보면 경로가 undefined가 뜬다.

경로를 아직 안만든 이유도 있는데 undefined는 무언가 잘못되었다.


session에서가져오는 key가 avartarUrl인데 avatarUrl이라고 써놔서 undefined가 떴었다.
이제 사진이 잘뜬다.

사진은 잘 저장되는데 이전의 사진들도 모두 서버에 저장되는 문제가 있다.
서버는 꺼졌다 켜졌다 할 수 있는데 서버가 꺼진경우 업로드한 파일이 있다면 모두 날아가게 된다.