본문 바로가기

Others/NODE.JS

파일 업로드

파일업로드?


사용자가 선택한 파일을 업로드 하면 그 파일을 웹애플리케이션이 받아서 적당한 디렉토리에 놓는 방법이다.

사용자가 애플리케이션에 전달하는 데이터는 크게 (이전글까지 이 부분을 해결함)과 여러가지 정보가 담긴 파일(이미지 등)라고 할 수 있다.


파일을 선택한 폼에서 파일을 선택 한 후, 제출하면 웹애플리케이션의 특정 디렉토리로 그 파일이 위치하며 사용자에게 업로드한 파일의 이름을 보여주는 것을 만들어보자.


아쉽게도 express는 사용자가 업로드 한 파일을 어딘가에 저장하는 기능을 제공하고 있지 않기 때문에 그 기능을 실행할 수 있는 모듈을 설치해야 한다. 그 모듈은 multer. 이는 express를 이용해서 사용자가 전송한 파일을 어딘가에 전송하는데 잘 튜닝되어 있는 여러 모듈 중에 하나이다.


multer 설치하기하고 프로젝트에 추가 및 제어(Line 4 : 변수에 담기)


npm install --save multer


 



파일 업로드 양식(form)


multer라는 모듈을 통해 업로드 애플리케이션을 만들어보자

일단은 사용자가 등록한 정보를 서버로 전송하기 위한 수단이 필요하다. 그 때 사용하는 것이 form. 그거부터 만들어보자. (path: /upload)


1. Line 10 : 라우터 만들기


2. views_files에 upload.jade 만들기


Line 6 : (중요) 잉크타입(enctype)지정, 사용자가 전송한 데이터(파일)를 서버로 전송할 수 있게 한다.


  


3. post로 받은 라우터 만들기

Line 13 : 선택한 파일을 제출하게 되면 method를 post로 했다. 그래서 post로 접근한 데이터를 받기 위한 라우터를 만들어주어야 한다.




4. 사용자가 전송한 파일을 가져오기 (multer)


multer형 페이지에 보면, usage 부분에 샘플을 보고 그대로 사용하면 된다.



Line 5 추가 : multer라는 모듈이 사실은 함수이다.

그 함수에 옵션(설정)을 주어서 실행시키면, multer() 함수는 업로드를 받을 수 있는 미들웨어를 리턴해주게된다.

그 제어를 변수 upload에 담아 진행한다. dest(destination;목적지) 사용자가 업로드한 파일이 애플리케이션의 디렉토리 중에 어디에 최종적으로 저장되어야 할지 지정하는 것. 설정값으로 uploads/했다면 'uploads'라는 디렉토리를 만들어야 한다.







Line 14 : upload.single('avatar')


의미: 사용자가 전송한 데이터에서 만약에 파일이 포함되어 있다면 파일을 가공해서 request객체에 file이라는 프로퍼티를 multer라는 모듈을 통해서 추가하는 코드. (정확히는 미들웨어.)


이제껏 썼던 app.post()와는 조금 다르다.

사용자가 POST 방식으로 전송한 데이터가 첫번째 인자에 담긴 디렉토리를 향하고 있다면 세번째 함수가 실행된다는 것은 알고 계시죠?


세번째 인자가 실행되기 전에 새로 추가한 두번째인자가 먼저 실행이 된다.

두번째 인자를 거쳐 세번째 인자(callback)가 실행될 때, 그 callback 함수의 req안에 file이라는 프로퍼티를 사용할 수 있게 된다.


Line 15 : 이렇게 작성하고 나면 다음과 같은 에러를 확인할 수 있는데, 그 이유는 바로 avatar 때문이다.

이 부분을 file 타입의 input이 name과 일치해주어야 한다.




(Line 14의 두번째 인자의 괄호 안 코드 변경)





일치해 준 다음에 다시 실행하면 객체라는 것을 보여주는 화면이 다시 나타난다.










다시한번 두번째 인자로 추가한 upload.single('input_type[file]_name')을 정의해보면,

미들웨어가 세번째인자(callback)가 실행되기 전에 실행되서, 함수가 받을 req객체의 file이라는 프로퍼티의 사용자가 전송한 파일에 대한 정보를 넣어준 것이다. req.file 프로퍼티를 통해서 사용자가 전송한 파일의 여러가지 정보를 알 수 있다.


Line 15 : 정보를 알아보자. console.log();


  • fieldname : form에서 input='file'의 name값
  • originalname : 파일의 이름
  • mimetype : 전송한 파일이 이미지 형식의 png 폼을 쓰고 있다는 뜻
  • destination : Line 5에서 지정한 목적지(dest)를 의미
  • filename : 내가 아무것도 하지 않고 이 상태로 파일을 전송했을 때, 전송한 파일은 destination이라는 디렉토리 밑에 해당 이름으로 저장된다.
  • path : 전송한 파일의 최종적인 경로. destination/filename
  • size : 전송된 파일의 크기




기본적으로multer는 사용자가 전송한 파일을 Line 5의 dest에 지정된 폴더에 저장하게 되는데, 저장 시 파일의 이름을 랜덤하게 만든다.

똑같은 파일이라도 새로운 이름의 파일이 생성되고 있었다. 그 기능을 확장하기 위해서는 메뉴얼을 자세히 들어보는 습관을 들이자.



dest이외의 옵션이 무엇이 있나 한번 보면,


storage : 문서를 보면 storage라는 변수를 담은 것을 볼 수 있는데, 그 변수에는 객체가 담겨 있다.


Line 5 : multer가 가지고 있는 diskStorage라는 메소드를 호출함으로써 storage 객체를 호출한다.

Line 6 - 11 : diskStorage 안에는 객체리터럴을 가지고 있고, destination함수과 filename함수가 담겨있다.

- destination() : 사용자가 전송한 파일을 어떤 디렉토리에 저장할지.

- filename() : 그 디렉토리에 저장할 파일의 이름을 정하는 것.


Line 14 : multer(사용자가 전송한 파일의 업로드와 관련된 일을 처리하면서) ({ storage(가 가리키고 있는 Line 6-11에서) : storage(destination, file 함수를 실행시키는 약속.)});



Line 7, 10 : 이 함수가 실행 됐을 때, 적당한 디렉토리와 적당한 파일의 이름을 가질 수 있도록 하는 코드.


세번째 인자로 전달된 콜백함수(cb)를 통해서

destination 또는 filename 안에서 cb를 호출하면서 그 두번째 인자로 파일이 저장될 경로를 주거나, 그 파일의 제목을 지정해주면 된다.




그리고 함수 안에 여러가지를 추가해서 사용자로 하여금 높은 자유도를 줄 수 있다. (if문사용)


ex)

- destination : 파일의 형식이 이미지면 A 디렉토리에 저장, 어디에 넣고, 텍스트면 B디렉토리에 저장.

- filename : 동일한 이름을 가진 파일이 있다면, 동일 이름의 파일 중에 가장 큰 숫자를 끝에 붙이기.


업로드한 파일을 사용자들이 볼수 있게 하고 싶다면?


이미 정적인 파일을 어떻게 서비스 하는지 살펴보았다. 그 방법을 생각해보면된다.

express 홈페이지에 가보면 static(정적)파일을 적용하는 예제가 있다.


방법1 : app.use(express.static('가져올파일이담겨진경로;));

방법2 : app.use( /user, 가져올파일이담겨진경로 ) = URL로 /user/파일명 으로 접근시 해당 파일 내용을 볼 수 있다. (Line 18)