[React] 고객관리 사이트에 이미지 업로드 부분 추가

2022. 8. 5. 17:17·Stack/React

2022.07.21 - [Coding/React] - [React] 고객관리 사이트 (Client) redux로 구현하기

 

[React] 고객관리 사이트 (Client) redux로 구현하기

2022.07.07 - [Coding/React] - [React] 고객관리 사이트 구현 (Client) [React] 고객관리 사이트 구현 (Client) green_customer_client Header Footer CustomerList Customer DetailCustomer - 라이브러리 설치 a..

7ingout.tistory.com

 

2022.08.03 - [Coding/React] - [React] 회원가입 기능 구현 (MySQL / bcrypt / 쿠키)

 

[React] 회원가입 기능 구현 (MySQL / bcrypt / 쿠키)

2022.07.21 - [Coding/React] - [React] 고객관리 사이트 (Client) redux로 구현하기 [React] 고객관리 사이트 (Client) redux로 구현하기 2022.07.07 - [Coding/React] - [React] 고객관리 사이트 구현 (Client)..

7ingout.tistory.com

 

1.customer_gallery 테이블 추가하기

1) 테이블 생성

crate table customer_gallery(

no int primary key,

imgurl varchar(45),

title varchar(100),

desc text

usermail varchar(45)

)

2) 외래키 지정하기

ALTER TABLE customer_gallery

Add FOREIGN KEY (usermail)

REFERENCES customer_members (usermail)

ON UPDATE CASCADE ON DELETE RESTRICT;

 

2. 서버 파일 업로드 설정하기

MIDDLEWARE-GREEN-CUSTOMER-SERVER

 npm install multer

https://www.npmjs.com/package/multer

 

multer

Middleware for handling `multipart/form-data`.. Latest version: 1.4.5-lts.1, last published: 2 months ago. Start using multer in your project by running `npm i multer`. There are 3368 other projects in the npm registry using multer.

www.npmjs.com

 

index.js

// 이미지 업로드 하는 부분

const multer = require("multer")
app.use("/upload", express.static("upload"));
// 파일 요청시 파일이 저장될 경로와 파일이름(요청된 원본파일이름) 지정
const storage = multer.diskStorage({
    destination:"./upload",
    filename: function(req, file, cb) {
        cb(null, file.originalname); // 원본 파일 이름과 똑같이 저장하겠다
    }
})

// 업로드 객체
const upload = multer({
    storage: storage,
    limits: { fieldSize: 1000000 }
})

// upload 경로로 post 요청이 왔을 경우 응답
app.post("/upload", upload.single("img"), function(req, res, next){
    res.send({
        imageUrl: req.file.filename
    })
})

// gallery post, get

// gallery post 요청
app.post('/gallery', async(req,res) => {
    const { usermail, title, imgurl, desc} = req.body;
    connection.query("insert into customer_gallery(`title`, `imgurl`, `desc`, `usermail`) values(?,?,?,?)",
    [title, imgurl, desc, usermail],
    (err, result, fields) => {
        res.send("등록되었습니다.");
        console.log(err);
    })
})

// gallery get 요청
app.get("/gallery", async (req, res)=> {
    connection.query("select * from customer_gallery",
    (err, result, fields)=> {
        res.send(result)
    })
})

 

MIDDLEWARE-GREEN-CUSTOMER-CLIENT

components/CreateGallery.js

import React, { useState } from 'react';
import { Table, TableBody, TableRow, TableCell } from '@mui/material';
import axios from "axios";
import { API_URL } from '../config/contansts';
import './GalleryStyle.css'
import { getCookie } from '../util/cookie'
import { useNavigate } from 'react-router-dom';

const CreateGallery = () => {
    const navigate = useNavigate()
    const umail = getCookie("usermail")
    const [ formData, setformData ] = useState({
        imgurl:"",
        title:"",
        desc:"",
        usermail:umail
    });
    const onChange = (e) => {
        const { name, value } = e.target;
        setformData({
            ...formData,
            [name]: value
        })
    }
    const onChangeImg = (e) => {
        const { name } = e.target;
        const imgFormData = new FormData();
        imgFormData.append(name, e.target.files[0]);
        axios.post(`${API_URL}/upload`, imgFormData, {
            Headers: {'content-type':'multipart/form-data'},
        }).then (response=>{
            // setUploadImg(response.data.imageUrl);
            setformData({
                ...formData,
                imgurl: response.data.imageUrl
            })
        }).catch(e=>{
            console.log(e)
        })
    }
    const onSubmit = (e) => {
        e.preventDefault();
        axios.post(`${API_URL}/gallery`, formData)
        .then(res=> {
            alert('등록되었습니다.');
            navigate('/');
        }).catch(e=> {
            console.log(e);
        })
    }
    return (
        <div>
            <h2>이미지 게시글 등록하기</h2>
            <form onSubmit={onSubmit}>
                <Table>
                    <TableBody>
                        <TableRow>
                            <TableCell>이메일</TableCell>
                            <TableCell>
                                <input name="username" type="text"
                                value={formData.usermail}
                                onChange={onChange} readOnly />
                            </TableCell>
                        </TableRow>
                        <TableRow>
                            <TableCell>이미지보기</TableCell>
                            <TableCell>
                                <div className='imgDiv'>
                                    <div className='imgBox'></div>
                                    <input type="file" className='imgInput' name="img" onChange={onChangeImg}/>
                                    {
                                        formData.imgurl && <img src={`${API_URL}/upload/${formData.imgurl}`} alt="" className='imgview'/>
                                    }
                                </div>
                            </TableCell>
                        </TableRow>
                        <TableRow>
                            <TableCell>제목</TableCell>
                            <TableCell>
                                <input name="title" type="text"
                                value={formData.title}
                                onChange={onChange}/>
                            </TableCell>
                        </TableRow>
                        <TableRow>
                            <TableCell>내용</TableCell>
                            <TableCell>
                                <input name="desc" type="text"
                                value={formData.desc}
                                onChange={onChange}/>
                            </TableCell>
                        </TableRow>
                        <TableRow>
                            <TableCell colSpan={2}>
                               <button type="submit">등록</button>
                               <button type="reset">취소</button>
                            </TableCell>
                        </TableRow>
                    </TableBody>
                </Table>
            </form>
        </div>
    );
};

export default CreateGallery;

 

components/GalleryStyle.css

.imgDiv {
    position: relative;
}
.imgBox {
    width: 150px;
    height: 150px;
    background-color: darkseagreen;
}
.imgInput {
    position: absolute;
    width: 150px;
    height: 150px;
    left: 0;
    top: 0;
    opacity: 0;
}
.imgview {
    width: 150px;
    height: 150px;
    position: absolute;
    left: 0;
    top: 0;
}

 

components/Header.js   // 이미지 등록 li 추가

 { isLogin && 
                    <>
                        <li>{uname}님 환영합니다!</li>
                        <li onClick={logoutClick}>로그아웃</li>
                        <li><Link to="/">회원정보수정</Link></li>
                        <li><Link to="/gallery">이미지등록</Link></li>
                    </>
                }

 

App.js   // link 추가, 새로고침하면 풀리는 것두 수정

import './App.css';
// import CustomerList from './components/CustomerList';
import DetailCustomer from './components/DetailCustomer';
import Footer from './components/Footer';
import Header from './components/Header';
import { Route, Routes } from "react-router-dom";
// import CreateCustomer from './components/CreateCustomer';
import EditCustomer from './components/EditCustomer';
import CustomerContainer from './components/CustomerContainer';
import CreateCustomerContainer from './components/CreateCustomerContainer';
import JoinForm from './components/JoinForm';
import Login from './components/Login';
import CreateGallery from './components/CreateGallery';
import { useEffect } from 'react';
import { getCookie } from './util/cookie';
import { setLogin } from './modules/logincheck';
import { useDispatch } from 'react-redux';
// const customers = [
//   {
//     no: 1,
//     name: "고객",
//     phone: "01012345678",
//     birth: "19920206",
//     gender: "여성",
//     add: "울산시 남구"
//   },
//   {
//     no: 2,
//     name: "그린",
//     phone: "01012345678",
//     birth: "19920206",
//     gender: "남성",
//     add: "울산시 동구"
//   },
//   {
//     no: 3,
//     name: "kh",
//     phone: "01012345678",
//     birth: "19920206",
//     gender: "여성",
//     add: "울산시 남구"
//   }
// ]
function App() {
  const dispatch = useDispatch();
  const uname= getCookie('username');
  useEffect(()=>{
    if(uname){
      dispatch(setLogin())
    }
  },[])
  return (
    <div className="App">
      <Header />
      <Routes>
        {/* props로 위에 {customers}를 CustomerList로 전달 */}
        {/* <Route path="/" element={<CustomerList customers={customers}/>} /> */}
        <Route path="/" element={<CustomerContainer/>} />
        <Route path="/detailview/:no" element={<DetailCustomer/>} />
        <Route path="/edit/:no" element={<EditCustomer/>} />
        {/* <Route path="/write" element={<CreateCustomer/>} /> */}
        <Route path="/write" element={<CreateCustomerContainer/>} />
        <Route path="/join" element={<JoinForm />} />
        <Route path="/login" element={<Login />} />
        <Route path="/gallery" element={<CreateGallery/>}/>
      </Routes>
      <Footer/>
    </div>
  );
}

export default App;

 

modules/gallery.js

import { API_URL } from "../config/contansts";
import axios from "axios";

// 액션타입, 액션 생성함수, 초기값, 리듀서
const GET_GALLERY = "GET_GALLERY";
const GET_GALLERY_SUCCESS = "GET_GALLERY_SUCCESS";
const GET_GALLERY_ERROR = "GET_GALLERY_ERROR";

const initialState = {
    data: null,
    loading: false,
    error: null
}

// 액션 생성함수
// thunk 함수 사용
export const getGallery = () => async dispatch => {
    dispatch({ type: GET_GALLERY }) // 요청시작
    try {
        const response = await axios.get(`${API_URL}/gallery`)
        const gallerydata = response.data;
        dispatch({ type: GET_GALLERY_SUCCESS, payload: gallerydata })
    }
    catch(e) {
        dispatch({ type: GET_GALLERY_ERROR, payload: e})
    }
}

export default function gallery(state=initialState, action) {
    switch(action.type) {
        case GET_GALLERY:
            return {
                loading: true,
                data: null,
                error: null
            }
        case GET_GALLERY_SUCCESS:
            return {
                loading: false,
                data: action.payload,
                error: null 
            }
        case GET_GALLERY_ERROR:
            return {
                loading: false,
                data: null,
                error: action.payload
            }
        default:
            return state
    }
}

 

modules/index.js

import { combineReducers } from "redux";
import customers from './customers';
import logincheck from "./logincheck";
import gallery from "./gallery";

const rootReducer = combineReducers({ customers, logincheck, gallery });
export default rootReducer;

 

components/GalleryListContainer.js

import React, { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { getGallery } from '../modules/gallery'
import { API_URL } from '../config/contansts.js';

const GalleryListContainer = () => {
    const { data, error, loading } = useSelector(state=>state.gallery);
    const dispatch = useDispatch();
    //컴포넌트 마운트 후 게시글 요청하기
    useEffect(()=>{
        dispatch(getGallery(dispatch))
    },[dispatch])
    if(loading) return <div>로딩중입니다.</div>
    if(error) return <div>에러가 발생했습니다.</div>
    if(!data) return null
    return (
        <div>
            <ul>
                {data.map(da=><li>
                    <img src = {`${API_URL}/upload/${da.imgurl}`} width="300" alt="" />
                    <br/><span>{da.title}</span>
                </li>)}
            </ul>
        </div>
    );
};

export default GalleryListContainer;

'Stack > React' 카테고리의 다른 글

[React / 스터디] 영화 평점 사이트 구현하기  (2) 2022.11.21
[React / 스터디] 모두의 일기장 클론 코딩  (2) 2022.09.30
[React] 회원가입 기능 구현 (MySQL / bcrypt / 쿠키)  (0) 2022.08.03
[React] 고객관리 사이트 (Client) redux로 구현하기  (0) 2022.07.21
[React] json-server을 이용하여 데이터 받아오기  (0) 2022.07.15
'Stack/React' 카테고리의 다른 글
  • [React / 스터디] 영화 평점 사이트 구현하기
  • [React / 스터디] 모두의 일기장 클론 코딩
  • [React] 회원가입 기능 구현 (MySQL / bcrypt / 쿠키)
  • [React] 고객관리 사이트 (Client) redux로 구현하기
7ingout
7ingout
  • 7ingout
    Hello, 7ingout world!
    7ingout
  • 전체
    오늘
    어제
    • 분류 전체보기 (205)
      • Project (5)
      • Stack (173)
        • React (40)
        • JavaScript (50)
        • TypeScript (14)
        • HTML (11)
        • CSS (31)
        • Spring (9)
        • PHP (15)
        • SQL (3)
        • Python (0)
      • ETC (9)
      • Design (13)
        • Illustrator (6)
        • Photoshop (7)
      • Articloid (4)
        • 7ingout (4)
  • 공지사항

    • ☻
  • 인기 글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
7ingout
[React] 고객관리 사이트에 이미지 업로드 부분 추가
상단으로

티스토리툴바