일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- Three js
- androidId
- userevent_tracker
- Three-fiber
- Prism.js
- webrtc
- node
- Image Resize typescript
- Completer
- jszip
- swagger-typescript-api
- Redux
- methodChannel
- Game js
- web track
- babel
- Flutter
- Raycasting
- identifierForVender
- typescript
- REST API
- code editor
- Babel standalone
- react
- FirebaseAnalytics
- Excel
- KakaoMap
- RouteObserver
- uint8array
- uint16array
- Today
- Total
Never give up
React, Node - Image upload example 본문
해당 예제에서는 node로 이미지 업로드 및 이미지 리스트 및 이미지 가져오는 부분을 구현하고
react에서 이미지 업로드 및 가져와서 보여주기를 구현해봤습니다
서버쪽에 만든 api 3개
get : image/get-imglist 서버에 저장된 이미지 리스트를 가져옵니다
get : image/:url 서버에 저장된 이미지를 보여줍니다
post : image/upload 서버에 이미지를 업로드합니다
image/index
require('dotenv').config()
const formidable = require('formidable');
const express = require('express');
const fs = require('fs');
const router = express.Router();
const storageUrl = process.env.FILE_PATH
router.get('/get-imglist', (req, res) => {
let imgList = []
try {
fs.readdirSync(storageUrl).forEach((file) => {
imgList = [...imgList, file]
})
} catch (e) {
res.send({ code: -1, data: `Get file list error : ${e}` })
return
}
console.log(imgList)
if(imgList.length === 0){
console.log('no image')
res.send({code: -1, data: 'There is no saved image'})
return
}
res.send({ code: 1, data: imgList })
})
router.get('/:url', (req, res) => {
const url = req.params.url
if (fs.existsSync(`${storageUrl}${url}`)) {
fs.readFile(`${storageUrl}${url}`, (err, data) => {
res.end(data)
})
} else {
return res.send(`No file exists : ${url}`)
}
})
router.post('/upload', (req, res) => {
console.log('upload')
const form = formidable({ multiples: true });
form.parse(req, (err, fields, files) => {
console.log({ fields, files })
try {
const oldPath = files.file.filepath
const newPath = storageUrl + files.file.newFilename + `.${fields.type}`
console.log({ oldPath, newPath })
fs.copyFile(oldPath, newPath, (err) => {
if (err) throw err;
res.write('File uploaded')
})
res.send({ data: { fields, files }, code: 1 });
} catch (e) {
res.send({ data: `Image upload failed : ${e}`, code: -1 })
}
});
})
module.exports = router
먼저 image/get-imglist는 formidable의 readdir을 이용해서 이미지 파일들을 리스트 형태로 보내줍니다
(이미지가 저장되지 않은경우는 간단한 메시지만 보냄)
image/url은 formidable의 readfile로 data를 가져와서 보내줍니다
(없는 이미지 파일인 경우 메시지를 보냄)
image/upload는 formidable의 parse로 payload에 담긴 이미지 파일을 가져와서
temp폴더에 있는 파일을 formidable의 copyFile을 이용해서 새로운 경로로 복사를 해줍니다
(oldPath에 있는 임시파일을 newPath로 복붙)
api.js
const response = async (url, method, data, headers) => {
let result
let code
try {
const res = await axios({ url, method, data, headers })
result = res.data.data
code = res.data.code
if (res.status !== 200) {
throw new Error(`Failed to fetch. status : ${res.status}`)
}
} catch (e) {
result = e
code = -1
}
return {
data: result,
code
}
}
getImageList = async () => {
const res = await response(`${imageURL}/get-imglist`)
return {
code: res.code,
data: res.data
}
}
uploadImage = async (file, type) => {
const formData = new FormData()
formData.append('file', file)
formData.append('type', type)
const res = await response(`${imageURL}/upload`, 'POST', formData, { 'Content-Type': 'multipart/form-data;' })
return {
code: res.code,
data: res.data
}
}
getImageList에서 위에 만들은 get-imglist를 가져오는 용도로 간단한 get입니다
uploadImage는 upload를 할 때 사용하는 post인데, 데이터를 넣어줄때 formData 형태로 넣어주고
헤더에 content-type에 multipart/form-data넣어줘서 보내줍니다
image_upload.js
import React, { Component } from 'react'
import { API } from 'api/common'
import { Link } from 'react-router-dom'
import { ToastContainer, toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
class ImageUploadExample extends Component {
constructor() {
super()
this.state = {
hasImage: false
}
this.api = new API()
this.file = null
this.type = null
}
getImageListFromServer = async () => {
const res = await this.api.getImageList()
console.log({ res })
if (res.code === 1) {
window.localStorage.setItem('imgList', res.data)
toast('이미지 리스트 보기 버튼을 눌러주세요')
this.setState({hasImage: true})
} else {
toast(res.data)
}
}
getImage = (e) => {
e.preventDefault()
this.file = e.target.files[0]
this.type = `${this.file.type}`.split('/')[1]
console.log(e, this.file, this.type)
}
uploadImage = async () => {
if (this.file === null) {
alert('No image selected')
return
}
if (this.type === null) {
alert('Unknown image type')
return
}
const res = await this.api.uploadImage(this.file, this.type)
if (res.code === 1) {
toast('이미지 업로드 완료')
} else {
toast(res.data)
}
}
render() {
return (
<>
<label>
파일업로드
<input type='file' accept='image/*' onChange={this.getImage} />
</label>
<button onClick={() => this.uploadImage()}>
업로드
</button>
<div style={{ margin: '10px 0 10px 0' }}>
<button onClick={() => this.getImageListFromServer()}>
이미지 리스트 가져오기
</button>
</div>
{this.state.hasImage ? (<Link to={'/img-list'}>
이미지 리스트 보기
</Link>) : <></>}
<ToastContainer />
</>
)
}
}
export default ImageUploadExample
화면은 간단하게 label을 붙여준 input 그리고 업로드 버튼(uploadImage용도)
그리고 이미지 가져오는 버튼 그리고 이미지 리스트를 보여줄 Link로 되어있고
각각 필요한 메소드를 만들어줬습니다
getImage는 클라이언트에서 이미지를 가져오는 용도
uploadImage는 버튼을 눌렀을 때 위에 만든 api를 이용해서 post
getImageListFromServer는 이미지 리스트를 가져와서 로컬스토리지에 저장 및 알림 용도
image_list.js
import React, { Component } from 'react'
import ImageBlock from 'route/imageblock/imageblock'
import { Center } from 'style/styled'
const imgBaseUrl = 'http://localhost:3000/image'
class ImageList extends Component {
constructor() {
super()
this.imageData = window.localStorage.getItem('imgList')
if (this.imageData !== null) {
this.imageList = []
this.imageData.split(',').forEach((e) => {
this.imageList.push(`${imgBaseUrl}/${e}`)
})
}
}
componentWillUnmount() {
window.localStorage.removeItem('imgList')
}
render() {
if (this.imageList) {
return (
<ImageBlock imageList={this.imageList} title='업로드 이미지' />
)
}
return (
<Center height='100vh'>
이미지 불러오는중...
</Center>
)
}
}
export default ImageList
이 부분은 이미지를 보여주는 부분으로
로컬 스토리지에 저장되어있는 이미지를 imageblock을 통해 보여주는 부분입니다
'WEB' 카테고리의 다른 글
Node - Nodemailer example (2) | 2022.04.26 |
---|---|
Node - Google analytics (feat. Chart.js, Excel) (0) | 2022.04.22 |
React - Kakaomap example (0) | 2022.02.19 |
React - html, css album page clone (0) | 2022.01.08 |
React, Node - Rest API with sqlite3 (beginner) - 2 (0) | 2022.01.08 |