현재 - (10) csv 파일 handsontable로 연동하기
다음 - (11) AutoSizeInput에 파일 이름 연동하기
이제 file까지 불러오게 되었으니, 실제 csv를 handsontable로 보여주자.
node js에 getFile.js를 추가한다.
readFileSync를 이용하여 utf-8로 file을 읽어서 send한다.
// getFile.js
const express = require("express");
const fs = require("fs");
const router = express.Router();
router.get("/", (req, res) => {
let path = req.query.path;
let info = fs.readFileSync(`${path}`, "utf8");
res.send({ info });
});
module.exports = router;
getFile.js를 추가하였으니 server.js에도 추가한다.
//server.js
const express = require('express');
const app = express();
const nodetest = require('./routes/nodetest');
const getFileFolderList = require('./routes/getFileFolderList');
const getFile = require('./routes/getFile');
const cors = require('cors');
app.use(cors()); //npm install cors --save
app.use('/nodetest', nodetest);
app.use('/getFileFolderList', getFileFolderList);
app.use('/getFile', getFile);
app.listen(3002, () => console.log('Node.js Server is running on port 3002...'));
이제 react의 nodelibrary.js에 getFile 함수를 만든다.
//nodelibrary.js
...
export const getFile = (path) => {
fetch(`${MY_SERVER}/getFile?path=${path}`)
.then((response) => response.json())
.then((data) => console.log(data));
}
App.js에 아래의 useEffect 코드를 추가하고, option에서 file을 고르면 파일 내용을 로그로 볼 수 있다.
useEffect(() => mnode.getFile(`${mnode.PATH}/${version}/${country}/${file}`), [file]);
참고로 모든 csv 파일은 아래와 같은 내용이 담겨있다.
이제 App.js의 csv 파일의 path 정보가 되는 version, country, file을 FileUpload에 넘겨주자.
handsontable에서 upload 코드를 재활용하면 server의 csv를 바로 불러올 수 있다.
아래와 같이 pathInfo에 version, country, file을 한꺼번에 담자.
<FileUpload setCsvObject={setCsvObject} pathInfo={{ version, country, file }} />
해당 file의 이름을 저장해두기 위해 useState를 만든다.
//App.js
...
const App = () => {
...
const [file, setFile] = useState("");
이 file 변수는 MyFileList에서 파일 이름이 변할 때 저장되어야 한다.
//MyFileList.js
...
const MyFileList = ({fileList, setFile}) => {
return (
<div>
<form>
<span>FileName : </span>
<select onChange={(e) => setFile(e.target.value)}>
<option value="">선택하세요.</option>
{fileList.map((item) => getOptionsForVersion(item))}
</select>
</form>
</div>
);
};
export default MyFileList;
FileUpload.js에서는 pathInfo를 추가하고 uploadOptionFile 함수를 만들자.
이전 코드도 파일을 업로드하면 library.js의 handleUpload에서 parsingCsv가 handsontable에 csv를 보여주었다.
uploadOptionFile은 path가 정상인 경우에 fetch의 then에서 parsingCsv를 호출하도록 하면 된다.
(MY_SERVER를 사용하기 위해 nodelibrary.js에서 MY_SERVER에 export를 선언해둬야 한다.)
// FileUpload.js
...
const FileUpload = ({ setCsvObject, fileUploadFlag, flagOn, flagOff, pathInfo }) => {
...
const uploadOptionFile = () => {
const { version, country, file } = pathInfo;
if(version === "" || country === "" || file === "") return;
flagOn();
let filePath = `${mnode.PATH}/${version}/${country}/${file}`;
fetch(`${mnode.MY_SERVER}/getFile?path=${filePath}`)
.then((response) => response.json())
.then((data) => lib.parsingCsv(data.info, setCsvObject));
}
useEffect(uploadOptionFile, [pathInfo.file]);
(parsingCsv에 대한 설명은 (6) csv 파일 파싱하기, (7) App.js에서 파싱된 csv 파일 받기 참고)
이때, uploadOptionFile에서 flagOn을 호출하지 않으면 아래의 에러가 발생한다.
MyTable.js에서 fileUploadFlag가 true인 경우만 id="hot-app"을 찾을 수 있는데,
flag가 off인 상태로 파일을 불렀기 때문에 handsontable을 create할 수 없어서 발생하는 에러다.
//MyTable.js
{fileUploadFlag && (
<div>
<button onClick={csvDownLoad}>DOWNLOAD</button>
<div>
<span>{displayIndex}</span>
<input value={displayCell} onChange={setValueCell} />
</div>
<div id="hot-app"></div>
</div>
)}
이제 server의 csv 파일도 불러올 수 있게 되었다.
최종 코드는 아래를 참고하자.
Node js
//server.js
const express = require('express');
const app = express();
const nodetest = require('./routes/nodetest');
const getFileFolderList = require('./routes/getFileFolderList');
const getFile = require('./routes/getFile');
const cors = require('cors');
app.use(cors()); //npm install cors --save
app.use('/nodetest', nodetest);
app.use('/getFileFolderList', getFileFolderList);
app.use('/getFile', getFile);
app.listen(3002, () => console.log('Node.js Server is running on port 3002...'));
// getFile.js
const express = require("express");
const fs = require("fs");
const router = express.Router();
router.get("/", (req, res) => {
let path = req.query.path;
let info = fs.readFileSync(`${path}`, "utf8");
res.send({ info });
});
module.exports = router;
React
//nodelibrary.js
export const MY_SERVER = `http://192.168.55.120:3002`;
export const PATH = `C:\\Users\\username\\Downloads\\TESTFILES`;
export const getFileFolderList = (path, fileExtension) => {
fetch(`${MY_SERVER}/getFileFolderList?path=${path}&fileExtension=${fileExtension}`)
.then((response) => response.json())
.then((data) => console.log(data));
}
export const getFolderList = (setState, path) => {
fetch(`${MY_SERVER}/getFileFolderList?path=${path}`)
.then((response) => response.json())
.then((data) => setState(data.folderList.map(list => list.name)));
}
export const getFileList = (path, fileExtension, setState) => {
fetch(`${MY_SERVER}/getFileFolderList?path=${path}&fileExtension=${fileExtension}`)
.then((response) => response.json())
.then((data) => setState(data.fileList.map(list => list.name)));
}
export const getFile = (path) => { /* this is for just test */
fetch(`${MY_SERVER}/getFile?path=${path}`)
.then((response) => response.json())
.then((data) => console.log(data));
}
//App.js
import React, { useEffect, useState } from "react";
import FileUpload from "./components/FileUpload";
import MyFileList from "./components/MyFileList";
import MyTable from "./components/MyTable";
import MyToggles from "./components/MyToggles";
import * as mnode from "./components/nodelibrary";
const csvObjectDefault = {
HEIGHT: 0,
WIDTH: 0,
csv: [],
};
const nodeTest = () => {
mnode.getFileFolderList(mnode.PATH, "csv");
return;
}
const App = () => {
const [csvObject, setCsvObject] = useState(csvObjectDefault);
const [version, setVersion] = useState("");
const [country, setCountry] = useState("");
const [file, setFile] = useState("");
const [fileList, setFileList] = useState([]);
const getFileList = () => {
if(version === "" || country === "") return;
let path = `${mnode.PATH}/${version}/${country}`;
mnode.getFileList(path, "csv", setFileList);
}
useEffect(getFileList, [version, country]);
return (
<div>
<MyToggles
version={version}
setVersion={setVersion}
country={country}
setCountry={setCountry}
/>
<hr style={{ borderColor: "grey" }} />
<MyFileList fileList={fileList} setFile={setFile}/>
<button onClick={nodeTest}>서버 연결</button>
<button onClick={() => console.log(csvObject)}>print csv</button>
<div className="App">
<FileUpload setCsvObject={setCsvObject} pathInfo={{ version, country, file }} />
<MyTable csvFile={csvObject}/>
</div>
</div>
);
};
export default App;
//MyFileList.js
import React from "react";
const getOptionsForVersion = (item) => {
return (
<option key={item} value={item}>
{item}
</option>
);
};
const MyFileList = ({fileList, setFile}) => {
return (
<div>
<form>
<span>FileName : </span>
<select onChange={(e) => setFile(e.target.value)}>
<option value="">선택하세요.</option>
{fileList.map((item) => getOptionsForVersion(item))}
</select>
</form>
</div>
);
};
export default MyFileList;
// FileUpload.js
import React, { useState, useEffect } from "react";
import { connect } from "react-redux";
import { actionCreators } from "./store";
import * as lib from "./library.js";
import * as mnode from "./nodelibrary";
import "../css/FileUpload.scss";
const FileUpload = ({ setCsvObject, fileUploadFlag, flagOn, flagOff, pathInfo }) => {
const [dropFlag, setDropFlag] = useState(false);
const onClickFileLoad = () => {
let my_input = document.getElementById("my-input");
my_input.click();
};
const uploadOptionFile = () => {
const { version, country, file } = pathInfo;
if(version === "" || country === "" || file === "") return;
flagOn();
let filePath = `${mnode.PATH}/${version}/${country}/${file}`;
fetch(`${mnode.MY_SERVER}/getFile?path=${filePath}`)
.then((response) => response.json())
.then((data) => lib.parsingCsv(data.info, setCsvObject));
}
useEffect(uploadOptionFile, [pathInfo.file]);
return (
<div>
{fileUploadFlag && <button onClick={onClickFileLoad}>불러오기</button>}
<input
id="my-input"
style={{ visibility: "hidden" }}
type="file"
accept=".csv"
onChange={(e) => lib.handleUpload(e, setCsvObject, flagOn)}
/>
{!fileUploadFlag && (
<div
id="drag-drop-field"
className={dropFlag ? "in" : ""}
onDrop={(e) => lib.handleOnDrop(e, setDropFlag, setCsvObject, flagOn)}
onDragOver={(e) => lib.handleDragOver(e, setDropFlag)}
onDragLeave={(e) => lib.handleOnDragLeave(e, setDropFlag)}
>
<p>drag & drop</p>
<input
type="file"
accept=".csv"
onChange={(e) => lib.handleUpload(e, setCsvObject, flagOn)}
/>
</div>
)}
</div>
);
};
function mapStateToProps(state, ownProps) {
//console.log(state);
return { fileUploadFlag: state };
}
function mapDispatchToProps(dispatch, ownProps) {
return {
flagOn: () => dispatch(actionCreators.flagOn()),
flagOff: () => dispatch(actionCreators.flagOff()),
};
}
export default connect(mapStateToProps, mapDispatchToProps)(FileUpload);
'개발 > Node JS' 카테고리의 다른 글
Node js, React 파일 관리 시스템 만들기 (12) (0) | 2021.07.18 |
---|---|
Node js, React 파일 관리 시스템 만들기 (11) (0) | 2021.07.17 |
Node js, React 파일 관리 시스템 만들기 (9) (0) | 2021.07.16 |
Node js, React 파일 관리 시스템 만들기 (8) (0) | 2021.07.15 |
Node js, React 파일 관리 시스템 만들기 (7) (0) | 2021.07.15 |
댓글