File upload

steyu·2022년 12월 9일
0

client submit

  • input type="file"
  • enctype="multipart/form-data" (default is "application/x-www-form-urlencoded", form에 파일이 하나이상 있으면 multipart/form-data"을 사용)
  • accept="image/jpg,image/png"
<form
	action="/profiles" 
	method="POST" 
	enctype="multipart/form-data">
	<input 
		type="file" 
		id="image" 
		name="image" 
		required
		accept="image/jpg,image/png" 
     />
</form>

server file upload

app.use(express.urlencoded({ extended: false })); 는 multipart/form-data파일을 처리할 수 없다.
그래서 파일업로드를 위해 다른 미들웨어를 추가해야한다.

npm i --save multer

모든요청에 적용하지 않고, 파일과 관련된 요청에만 특정 미들웨어를 쓰는 방법

  • upload.single("image"): name="image"인 싱글 파일
  • req.file
// app.js
const multer = require("multer");
const upload = multer({});

router.post("/profiles", upload.single("image"), async (req, res) => {
  const uploadedImageFile = req.file;
  const userData = req.body;
});

multer gives us

  • access to the file
  • automatically store image on server side.

어디에 파일을 저장할까?

데이터베이스에 파일자체는 저장하지 않고, 파일경로를 저장한다.
파일은 파일시스템 하드드라이브 어딘가에 저장한다 (파일작업에 최적화이기 때문)

파일을 파일시스템에 저장하고, 그 파일경로를 데이터베이스에 저장

따라서 multer에게 어디에 파일을 저장하는지 설정해야한다

multer config

  • multer.diskStorage({destination, filename}): 파일이 저장될 곳, 파일 이름 설정
  • multer({storage})
const express = require("express");
const multer = require("multer");

const storageConfig = multer.diskStorage({
  destination: function (req, file, cb) {
    // error, destination
    cb(null, "images"); 
  },
  filename: function (req, file, cb) {
    // error, filename
    cb(null, Date.now() + "-" + file.originalname);
  },
});
const upload = multer({
  storage: storageConfig,
});

router.post("/profiles", upload.single("image"), (req, res) => {
  const uploadedImageFile = req.file;
  const userData = req.body;
  
  // store filepath, data to db
  await db.getDb().collection("users").insertOne({
    name: userData.username,
    imagePath: uploadedImageFile.path,
  });

  res.redirect("/");
});

저장된 파일 렌더하기

<img src="<%= user.imagePath %>" alt="The image of the user.">

imagePath를 src에 전달했는데 밑의 에러가 뜸

이유는?

사용자는 서버측 파일에 접근할 수 없다 (images 폴더에 접근불가. 보안)

해결법?

static 미들웨어를 통해 (이미 저장된 정적파일은 이렇게 불러온다)

app.use(express.static('images'))

=> 정적폴더이름은(images) 링크의 일부가 아니다.
/images/filename이 아니라 filename 자체를 요청해야한다.

app.use('/images', express.static('images'))
/images경로 요청일때만 express.static('images') 이 미들웨어가 active된다는 뜻

이미지 preview

public폴더 안에 styles, scripts to serve files directly

  • addEventListener('change', function)
  • element.files
  • ele.src = URL.createObjectURL(file): 파일을 가져와서 convert to url
const filePickerElement = document.getElementById("image");
const imagePreviewElement = document.getElementById("image-preview");

function showPreview() {
  const files = filePickerElement.files;
  if (!files || files.length === 0) {
    imagePreviewElement.style.display = "none";
    return;
  }
  const pickedFile = files[0];
  imagePreviewElement.src = URL.createObjectURL(pickedFile); // local url
  imagePreviewElement.style.display = "block";
}

filePickerElement.addEventListener("change", showPreview);

0개의 댓글

관련 채용 정보