구글의 Timeline 데이터는 Json 파일인데 이걸 멀티로 업로드하는 기능이 필요한데,
화면을 따로 빼기보다는 dialog로 팝업창 띄우는 방식으로 해보았다
material-ui에 Dialog를 활용했고, 텍스트와 버튼을 추가하고 업로드하는 영역도 추가된 모습
https://material-ui.com/components/dialogs/#dialog
에 있는 부분을 그대로 붙여넣음
100번 라인에 JsonUpload라는 컴포넌트가 실제 업로드하고 업로드된 데이터를 눈으로 보는 부분이 되겠다
여기는 업로드 버튼을 눌렀을 때 타는 로직인데 중복된 이름으로 업로드 된것도 체크해줘야하고, 확장자가 json이 아닌경우도 걸러주면 좋을것 같다
이미지 업로드하는 부분과 똑같이 처리하였다
import React, { useEffect, useState } from 'react';
import Button from '@material-ui/core/Button';
import Dialog from '@material-ui/core/Dialog';
import DialogActions from '@material-ui/core/DialogActions';
import DialogContent from '@material-ui/core/DialogContent';
import DialogContentText from '@material-ui/core/DialogContentText';
import DialogTitle from '@material-ui/core/DialogTitle';
import Slide from '@material-ui/core/Slide';
import JsonUpload from '../../../utils/JsonUpload'
import axios from 'axios'
const Transition = React.forwardRef(function Transition(props, ref) {
return <Slide direction="up" ref={ref} {...props} />
})
function TlUploadPage() {
const [open, setOpen] = useState(false)
const [Files, setFiles] = useState([])
const [FilePath, setFilePath] = useState([])
useEffect(() => {
if(FilePath) {
console.log(' Path >>', FilePath)
}
}, [FilePath])
const handleClickOpen = () => {
setOpen(true)
}
const handleClear = () => {
setFiles([])
}
const handleClose = () => {
setOpen(false)
}
const handleUpload = () => {
if(Files.length === 0) return
for(let i = 0; i < Files.length; i++){
for(let j = 0; j < Files.length; j++){
if(Files[i].name === Files[j].name && i !== j){
alert(`${Files[i].name} 파일이 중복됩니다!`)
return
}
}
}
let formData = new FormData()
for(let i = 0; i < Files.length; i++){
formData.append("file", Files[i])
}
const config = {
headers: {
'Content-Type': 'multipart/form-data'
}
}
axios.post('/api/polyline/dataupload', formData, config)
.then(response => {
if(response.data.success){
let newPath = []
response.data.files.map((cur) => {
newPath.push(cur.path)
})
setFilePath(newPath)
setOpen(false)
} else{
alert('파일 업로드 실패!')
}
})
}
const onSetFiles = (files) => {
setFiles(files)
}
return (
<div style={{padding: '10px 15px'}}>
<div onClick={handleClickOpen}>
Data Upload
</div>
<Dialog
open={open}
TransitionComponent={Transition}
keepMounted
onClose={handleClose}
aria-labelledby="alert-dialog-slide-title"
aria-describedby="alert-dialog-slide-description"
>
<DialogTitle id="alert-dialog-slide-title">
Json 파일을 업로드하세요!
</DialogTitle>
<DialogContent>
{/* <DialogContentText id="alert-dialog-slide-description">
Text~~
</DialogContentText> */}
<JsonUpload
initFiles={Files}
updateFiles={onSetFiles}/>
</DialogContent>
<DialogActions>
<Button onClick={handleClear} color="primary">
초기화
</Button>
<Button onClick={handleClose} color="primary">
취소
</Button>
<Button onClick={handleUpload} color="primary"
disabled={Files.length > 0 ? false:true}>
업로드
</Button>
</DialogActions>
</Dialog>
</div>
)
}
export default TlUploadPage
지난 이미지업로드와 비슷하게, dropHandler에서 처리한다
붙인 데이터를 push해서 setState
해주고 상위 props로 올린다!
DeleteIcon을 추가해서 눌렀을 때, 파일에서 없애주고 마찬가지로 상위 props로 변경된 파일을 갱신해준다
import React, { useEffect, useState } from 'react'
import Dropzone from 'react-dropzone'
import { Icon } from 'antd'
import axios from 'axios'
import DeleteIcon from '@material-ui/icons/Delete';
function FileUpload(props) {
const [Files, setFiles] = useState([])
useEffect(() => {
setFiles(props.initFiles)
}, [props.initFiles])
const dropHandler = (files) => {
let newFiles = [...Files]
files.map((cur) => {
newFiles.push(cur)
})
setFiles(newFiles)
props.updateFiles(newFiles)
}
return (
<div style={{display:'flex', justifyContent:'space-between'}}>
<Dropzone
onDrop={dropHandler}
multiple>
{({getRootProps, getInputProps}) => (
<section>
<div style={{
width:200, height: 140, border:'1px solid lightgray',
display:'flex', alignItems: 'center', justifyContent:'center'
}}
{...getRootProps()}>
<input {...getInputProps()} />
<Icon type="plus" style={{ fontSize:'2rem'}}/>
</div>
</section>
)}
</Dropzone>
<div style={{ width:'400px', height: '140px', overflowY:'auto'}}>
{Files && Files.map((cur, index) => (
<div style={{margin: '0px 10px'}} key={index}>
{`# ${index+1} - ${cur.name}`}
<div style={{display:'inline-block', marginLeft: '5px'}}>
<DeleteIcon
style={{verticalAlign:'middle'}}
onClick={() => {
setFiles(Files.filter((file) => file !== cur))
props.updateFiles(Files.filter((file) => file !== cur))
}}/>
</div>
</div>
))}
</div>
</div>
)
}
export default FileUpload