일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
- 계산맞추기 게임
- JS 개념
- react
- 노드에 리액트 추가하기
- 자바스크립트
- node.js로 로그인하기
- Python
- 웹 게임을 만들며 배우는 리액트
- googleColaboratory
- node.js 설치
- intllij 내 Bean을 찾지 못해서 발생하는 오류
- vs code 내 node
- Spring-Framework
- intellij
- 타자 게임 만들기
- ReactDOM.render is no longer supported in React 18. Use createRoot instead
- 따라하며 배우는 노드 리액트 기본 강의
- DB Browser
- react오류
- Colaboratory 글자 깨짐
- 리액트
- 모두의 파이썬
- 모던자바스크립트
- props
- You are importing createRoot from "react-dom" which is not supported. You should instead import it from "react-dom/client"
- 인프런
- Do it 자바스크립트 + 제이쿼리 입문
- 거북이 대포 게임
- Concurrently
- spring-boot
- Today
- Total
프로그래밍 삽질 중
React로 이미지가 포함된 정보 server에 보내기 본문
* '따라하며 배우는 노드, 리액트 시리즈 - 쇼핑몰 사이트 만들기' 강의 참고
* react -> node.js로 이미지 및 정보 저장하기
* mongoDB에 저장하는 것까지 확인
[Client] - 연결 루트는 "localhost:5000/api/data/image"(server) / "localhost:3000/review/data"(client)
1. App.js
- /review/upload로 페이지 확인하도록 만들기
(auth부분은 https://ba-gotocode131.tistory.com/category/%EA%B0%9C%EC%9D%B8%EA%B3%B5%EB%B6%80/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8)에서 확인
2. Review/DataUpload.js
- 전반적인 upload 관련 내용
3. Review/FileUpload.js
- 이미지 저장 관련 내용
[Server]
1. app.js(일반적으로 index.js)
- router 연결
2. Models/Data.js
- 스키마를 제어하는 파일
3. routes/data.js
- 클라이언트에서 받아온 정보를 제어, 저장
- 저장장소 : review폴더(Client, Server와 다른 폴더에 존재)
[1. 설정하기]
[Server] - 연결 루트는 "localhost:5000/api/data/image"(server) / "localhost:3000/review/data"(client)
1. app.js(일반적으로 index.js)
- router 연결
const express = require("express");
const app = express();
const bodyParser = require("body-parser");
require("dotenv").config();
const cookieParser = require("cookie-parser");
const config_conn = require("./config/key");
const mongoose = require("mongoose");
const PORT = process.env.PORT;
app.listen(PORT, () => {
console.log("서버 가동");
});
mongoose
.connect(config_conn.mongoURI, {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(() => console.log("MongoDB Connected"))
.catch((err) => console.log(err));
//body-parser
//application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }));
//application/json
app.use(bodyParser.json());
app.use(cookieParser());
//이 부분 추가
app.use("/api/data", require("./routes/data"));
app.use("/uploadReview", express.static("uploadReview"));
module.exports = app;
2. Models/Data.js
- 스키마를 제어하는 파일
const mongoose = require("mongoose");
const dataSchema = mongoose.Schema(
{
title: {
type: String,
},
description: {
type: String,
maxlength: 50,
},
images: {
type: Array,
default: [],
},
//시간 자동 업데이트
},
{ timestamps: true }
);
const Data = mongoose.model("Data", dataSchema);
module.exports = { Data };
3. routes/data.js
- 클라이언트에서 받아온 정보를 제어, 저장
- 저장장소 : review폴더(Client, Server와 다른 폴더에 존재)
const express = require("express");
const router = express.Router();
const multer = require("multer");
const { Data } = require("../models/review/Data");
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "review/");
},
filename: function (req, file, cb) {
cb(null, `${Date.now()}_${file.originalname}`);
},
});
var upload = multer({ storage: storage }).single("file");
router.post("/image", (req, res) => {
// 가져온 이미지를 저장을 해주면 된다.
upload(req, res, (err) => {
if (err) {
return req.json({ success: false, err });
}
return res.json({
success: true,
filePath: res.req.file.path,
fileName: res.req.file.filename,
});
});
});
module.exports = router;
[Client] - 연결 루트는 "localhost:3000/review/data"
1. App.js
- /review/upload로 페이지 확인하도록 만들기
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Auth from "./hoc/auth";
import DataUpload from "./components/views/Review/DataUpload";
function App() {
return (
<BrowserRouter>
<NavBar />
<Routes>
<Route path="/review/data" element={Auth(DataUpload, true)} />
</Routes>
</BrowserRouter>
);
}
export default App;
2. Review/DataUpload.js
- 전반적인 upload 관련 내용
import React from "react";
import { Button, Form, Input } from "antd";
// import axios from "axios";
// import { useNavigate } from "react-router-dom";
import FileUpload from "./FileUpload";
const { TextArea } = Input;
function DataUpload() {
return (
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
width: "100%",
height: "100vh",
}}
>
<div style={{ textAlign: "center", marginBottom: "2rem" }}>
<br />
<br />
<br />
<h2>계절 관련 업로드</h2>
<Form>
<FileUpload />
<label>이름</label>
<Input />
<br />
<br />
<label>설명</label>
<TextArea />
<br />
<br />
<Button>확인</Button>
</Form>
</div>
</div>
);
}
export default DataUpload;
* 결과
3. Review/FileUpload.js
- 이미지 저장 관련 내용
import React, { useState } from "react";
import Dropzone from "react-dropzone";
import { PlusOutlined } from "@ant-design/icons";
import axios from "axios";
function FileUpload(props) {
const [Images, setImages] = useState([]);
const dropHandler = (files) => {
let formData = new FormData();
const config = {
header: { "content-type": "multipart/form-data" },
};
formData.append("file", files[0]);
axios
.post("/api/data/image", formData, config)
.then((response) => {
if (response.data.success) {
//console.log(response.data);
setImages([...Images, response.data.filePath]);
} else {
alert("파일을 저장하는데 실패했습니다.");
}
});
};
const deleteHandler = (image) => {
const currentIndex = Images.indexOf(image);
let newImages = [...Images];
newImages.splice(currentIndex, 1); //현재인덱스부터 다음 인덱스까지
setImages(newImages);
};
return (
<div style={{ display: "flex", justifyContent: "space-between" }}>
<Dropzone onDrop={dropHandler}>
{({ getRootProps, getInputProps }) => (
<section>
<div
style={{
width: 300,
height: 240,
border: "1px solid lightgray",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
{...getRootProps()}
>
<input {...getInputProps()} />
<PlusOutlined
style={{
fontSize: "3rem",
display: "flex",
alignSelf: "center",
}}
/>
</div>
</section>
)}
</Dropzone>
<div
style={{
display: "flex",
width: "350px",
height: "240px",
overflowX: "scroll",
}}
>
{Images.map((image, index) => {
return (
<div onClick={() => deleteHandler(image)} key={index}>
<img
style={{ minWidth: "300px", width: "300px", height: "240px" }}
src={`http://localhost:5000/${image}`}
/>
</div>
);
})}
</div>
</div>
);
}
export default FileUpload;
* 결과
[2. 클라이언트-서버에 data 보내기]
1. [Client]Review/DataUpload.js
- DataUpload에 Image 정보 보내기
import React, { useState } from "react";
import { Button, Form, Input } from "antd";
import axios from "axios";
import { useNavigate } from "react-router-dom";
import FileUpload from "./FileUpload";
const { TextArea } = Input;
function DataUpload() {
const [Title, setTitle] = useState("");
const [Description, setDescription] = useState("");
const [Images, setImages] = useState([]);
const navigate = useNavigate();
const titleChangeHandler = (event) => {
setTitle(event.currentTarget.value);
};
const descriptionChangeHandler = (event) => {
setDescription(event.currentTarget.value);
};
//추가1 : FileUpload의 값 받아오도록 함
const updateImages = (newImages) => {
setImages(newImages);
};
//추가2
const submitHandler = (event) => {
//페이지 자동 리프레시 되는 것 막음
event.preventDefault();
//값이 하나라도 비면 오류
if (!Title || !Description || !Images) {
return alert("모든 값을 작성해야 합니다.");
}
//값을 다 채우면 서버 request로 보낸다
const body = {
//로그인된 사람의 아이디
title: Title,
description: Description,
images: Images,
};
axios.post("/api/data", body).then((response) => {
if (response.data.success) {
alert("상품 업로드에 성공했습니다.");
navigate("/");
} else {
alert("상품 업로드에 실패했습니다.");
}
});
};
return (
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
width: "100%",
height: "100vh",
}}
>
<div style={{ textAlign: "center", marginBottom: "2rem" }}>
<br />
<br />
<br />
<h2>계절 관련 업로드</h2>
<Form onSubmitCapture={submitHandler}>
{/* FileUpload에서 refreshFunction으로 제어 */}
<FileUpload refreshFunction={updateImages}/>
<label>이름</label>
<Input onChange={titleChangeHandler} value={Title} />
<br />
<br />
<label onChange={descriptionChangeHandler} value={Description}>
설명
</label>
<TextArea />
<br />
<br />
<Button onClick={submitHandler}>확인</Button>
</Form>
</div>
</div>
);
}
export default DataUpload;
3. [Client]Review/FileUpload.js
- DataUpload로 정보 보내기
import React, { useState } from "react";
import Dropzone from "react-dropzone";
import { PlusOutlined } from "@ant-design/icons";
import axios from "axios";
function FileUpload(props) {
const [Images, setImages] = useState([]);
const dropHandler = (files) => {
let formData = new FormData();
const config = {
header: { "content-type": "multipart/form-data" },
};
formData.append("file", files[0]);
axios
.post("/api/data/image", formData, config)
.then((response) => {
if (response.data.success) {
//console.log(response.data);
setImages([...Images, response.data.filePath]);
//추가
props.refreshFunction([...Images, response.data.filePath]);
} else {
alert("파일을 저장하는데 실패했습니다.");
}
});
};
const deleteHandler = (image) => {
const currentIndex = Images.indexOf(image);
let newImages = [...Images];
newImages.splice(currentIndex, 1); //현재인덱스부터 다음 인덱스까지
setImages(newImages);
//추가
props.refreshFunction(newImages);
};
return (
<div style={{ display: "flex", justifyContent: "space-between" }}>
<Dropzone onDrop={dropHandler}>
{({ getRootProps, getInputProps }) => (
<section>
<div
style={{
width: 300,
height: 240,
border: "1px solid lightgray",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
{...getRootProps()}
>
<input {...getInputProps()} />
<PlusOutlined
style={{
fontSize: "3rem",
display: "flex",
alignSelf: "center",
}}
/>
</div>
</section>
)}
</Dropzone>
<div
style={{
display: "flex",
width: "350px",
height: "240px",
overflowX: "scroll",
}}
>
{Images.map((image, index) => {
return (
<div onClick={() => deleteHandler(image)} key={index}>
<img
style={{ minWidth: "300px", width: "300px", height: "240px" }}
src={`http://localhost:5000/${image}`}
/>
</div>
);
})}
</div>
</div>
);
}
export default FileUpload;
3. [Server]/routes/data.js
const express = require("express");
const router = express.Router();
const multer = require("multer");
const { Data } = require("../models/review/Data");
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "uploadReview/");
},
filename: function (req, file, cb) {
cb(null, `${Date.now()}_${file.originalname}`);
},
});
var upload = multer({ storage: storage }).single("file");
router.post("/image", (req, res) => {
// 가져온 이미지를 저장을 해주면 된다.
upload(req, res, (err) => {
if (err) {
return req.json({ success: false, err });
}
return res.json({
success: true,
filePath: res.req.file.path,
fileName: res.req.file.filename,
});
});
});
//client로 가져온 정보 저장
router.post("/", (req, res) => {
//받아온 정보를 DB에 저장함
const data = new Data(req.body);
data.save((err) => {
if (err) return res.status(400).json({ success: false, err });
return res.status(200).json({ success: true });
});
});
module.exports = router;
* 최종 결과
'과거 프로그래밍 자료들 > React' 카테고리의 다른 글
React로 이미지가 포함된 정보 DB에서 가져오기 (0) | 2022.05.22 |
---|---|
[React] 자주 언급되는 내용들 한 번 정리 (0) | 2022.05.22 |
React로 이미지 올리기 (0) | 2022.05.19 |
React로 option 값 넣고 변경하기 (0) | 2022.05.18 |
[인프런 강의]리액트 무비앱 시리즈5 - MovieDetail(2) (0) | 2022.05.17 |