이미지 파일이 포함된 폼데이터 post 요청을 express에서 받아서
프런트에 응답을 주려면 express의 multer를 사용해야 한다.
var multer = require('multer'); // express에 multer모듈 적용 (for 파일업로드)
var upload = multer({ dest: 'uploads/' })
// 입력한 파일이 uploads/ 폴더 내에 저장된다.
// multer라는 모듈이 함수라서 함수에 옵션을 줘서 실행을 시키면, 해당 함수는 미들웨어를 리턴한다.
app.post('/upload', upload.single('userfile'), function(req, res){
res.send('Uploaded! : '+req.file); // object를 리턴함
console.log(req.file); // 콘솔(터미널)을 통해서 req.file Object 내용 확인 가능.
});
미들웨어 upload.single('avatar')는 뒤의 function(req, res)함수가 실행되기 전에 먼저 실행.
미들웨어는 사용자가 전송한 데이터 중에서 만약 파일이 포함되어 있다면,
그 파일을 가공해서 req객체에 file 이라는 프로퍼티를 암시적으로 추가도록 약속되어 있는 함수.
upload.single('avatar') 의 매개변수 'avatar'는 form을 통해 전송되는 파일의 name속성을 가져야 함.
여기까지 해주면 파일 전송에도 성공하지만 파일명이 이진법으로 들어간다.
원본파일명으로 저장해주려면 아래와 같이 multer.disStorage를 사용해준다.
var multer = require('multer'); // multer모듈 적용 (for 파일업로드)
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads/') // cb 콜백함수를 통해 전송된 파일 저장 디렉토리 설정
}
filename: function (req, file, cb) {
cb(null, file.originalname) // cb 콜백함수를 통해 전송된 파일 이름 설정
}
})
var upload = multer({ storage: storage })
import styled from "styled-components";
import arrow from "../assets/arrow.png";
import { Link } from "react-router-dom";
import { useState } from "react";
import axios from "axios";
const PostForm = () => {
const [form, setForm] = useState({
name: "",
title: "",
posting: "",
});
const [imagefile, setImageFile] = useState(null);
const handleChange = (e) => {
const { name, value } = e.target;
setForm((prev) => ({ ...prev, [name]: value }));
};
const handleFileChange = (e) => {
const file = e.target.files[0];
setImageFile(file);
};
const handleSubmit = async (e) => {
e.preventDefault();
console.log("전송버튼");
try {
const formData = new FormData();
formData.append("name", form.name);
formData.append("title", form.title);
formData.append("posting", form.posting);
formData.append("image", imagefile);
console.log(imagefile);
const response = await axios.post(
"http://localhost:3001/create",
formData,
{
headers: {
"Content-Type": "multipart/form-data",
},
}
);
console.log(response.data);
} catch (error) {
console.error("Error occurred:", error);
}
};
return (
<PageWrapper>
<Link to="/">
<img src={arrow} alt="Arrow" />
</Link>
<Content>
<StyledForm onSubmit={handleSubmit} enctype="multipart/form-data">
<h2>Post your dress today</h2>
<StyledInput
name="name"
type="name"
placeholder="name"
value={form.name}
onChange={handleChange}
/>
<StyledInput
name="title"
type="text"
placeholder="Title"
value={form.title}
onChange={handleChange}
/>
<StyledInput
name="posting"
type="textarea"
placeholder="Posting"
value={form.posting}
onChange={handleChange}
/>
<div>
<InputLabel htmlFor="profileImage">
Choose what you dressed today:
</InputLabel>
<StyledInput
name="file"
type="file"
id="file"
onChange={handleFileChange}
/>
</div>
<ButtonWrapper>
<StyledButton>Submit</StyledButton>
</ButtonWrapper>
</StyledForm>
</Content>
</PageWrapper>
);
};
export default PostForm;
const PageWrapper = styled.div`
background-color: orange;
min-height: 100vh;
img {
width: 30px;
margin-top: 60px;
margin-left: 100px;
}
`;
const Content = styled.div`
flex-grow: 1;
display: flex;
justify-content: center;
align-items: center;
margin-top: 60px;
`;
const StyledForm = styled.form`
background-color: white;
padding: 40px;
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
`;
const StyledInput = styled.input`
width: 100%;
padding: 10px;
margin-bottom: 20px;
border: 1px solid #ccc;
border-radius: 5px;
box-sizing: border-box;
`;
const ButtonWrapper = styled.div`
display: flex;
justify-content: center;
`;
const StyledButton = styled.button`
padding: 10px 20px;
background-color: orange;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
font-weight: bold;
`;
const InputLabel = styled.label`
margin-bottom: 10px;
font-size: 12px;
`;
const express = require("express");
const multer = require("multer");
const mysql = require("mysql");
const cors = require("cors");
const app = express();
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "uploads/"); // cb 콜백함수를 통해 전송된 파일 저장 디렉토리 설정
},
filename: function (req, file, cb) {
cb(null, file.originalname); // cb 콜백함수를 통해 전송된 파일 이름 설정
},
});
const upload = multer({ storage: storage });
const db = mysql.createConnection({
host: "localhost",
user: "root",
password: "비번",
database: "데이타베이스이름",
});
db.connect();
app.use(cors());
app.use(express.json());
app.post("/create", upload.single("image"), (req, res) => {
const { name, title, posting } = req.body;
const image = req.file.filename; // 이미지 파일명
console.log("req입니다:", req);
console.log("req.body입니다:", req.body);
console.log("image입니다:", image);
// res.send("올렸습니다 :" + req.file);
console.log(req.file);
db.query(
`INSERT INTO topic (name, title, posting, image) VALUES (?, ?, ?, ?)`,
[name, title, posting, image],
(error, result) => {
if (error) {
throw error;
}
res.json(result);
}
);
});
app.listen(3001, () => {
console.log("Node.js 서버가 3001번 포트에서 실행 중입니다.");
});
참고블로그:
https://wayhome25.github.io/nodejs/2017/02/21/nodejs-15-file-upload/