koa2 + react16.8
github 地址連接javascript
1.建立react app
yarn create react-app my-app
2.用material-ui
編寫頁面,代碼以下html
<form action="/upload" method="post" encType="multipart/form-data" style={{width:'100%'}}> <div> <input accept="image/*" className={classes.input} id="contained-button-file" multiple type="file" onChange={uploadImg} /> <label htmlFor="contained-button-file"> <Button variant="contained" component="span" className={classes.button} > 添加圖片 </Button> </label> <GridList cellHeight={100} className={classes.gridList} cols={3}> {/*{console.log('html',values.images&&values.images)}*/} { values.images && values.images.map((item,index) => ( <GridListTile key={index} cols={item.cols || 1} data-index = {index} > <strong>{item.name}</strong> <a href="javascript:void(0)" className="upload-delete" title="刪除" data-index = {index} onClick={deleteImg} >刪除{index}</a> <br/> <img src={item.thumb} /> </GridListTile> ))} </GridList> </div> </form> { values.images &&values.images.length ? <Button variant="contained" color="primary" style={{height:'40px',width:'20%'}} className={classes.margin} onClick={() => handleUpload()}> 上傳圖片 </Button>:'' }
3.其中須要用的函數代碼以下:前端
const classes = useStyles(); const [values, setValues] = React.useState({ age: '', images:[], uploadHistory:[], }); function uploadImg(e) { e.preventDefault(); let target = e.target; let files = target.files; let count = files.length; for (let i = 0; i < count; i++) { files[i].thumb = URL.createObjectURL(files[i]) } // convert to array //Array.prototype.slice.call(arguments)能將具備length屬性的對象(key值爲數字)轉成數組。 // []是Array的示例,因此能夠直接使用[].slice()方法。 files = Array.prototype.slice.call(files, 0); files = files.filter(function (file) { return /image/i.test(file.type) }); setValues(oldValues => ({ ...oldValues, images: values.images.concat(files) })); } const deleteImg = (e) => { let index = e.target.getAttribute('data-index'); let result = values.images.splice(index,1); setValues(oldValues => ({ ...oldValues, images: values.images })); }; function handleUpload() { for (let i = 0, file; file = values.images[i]; i++) { ((file) => { let xhr = new XMLHttpRequest(); if (xhr.upload) { // 上傳中 console.log('上傳中') xhr.upload.addEventListener("progress", (e) => { // handleProgress(file, e.loaded, e.total, i); }, false); // 文件上傳成功或是失敗 xhr.onreadystatechange = (e) => { if (xhr.readyState == 4) { if (xhr.status == 200) { console.log('handleSuccess' ,file ) // handleSuccess(file, xhr.responseText); // this.handleDeleteFile(file); if (!values.images.length) { //所有完畢 handleComplete(); console.log('所有上傳完成!'); } } else { handleFailure(file, xhr.responseText); console.log('上傳出錯!'); } } }; const form = new FormData(); form.append("filedata", file); // 開始上傳 xhr.open("POST", "/upload", true); // xhr.setRequestHeader("FILENAME", file.name); console.log('form',form); xhr.send(form); } })(file) } } //當上傳圖片的時候,若是還須要從前端日後端傳參數能夠使用`form.append("filedata", file);`的方法
1.koa搭建框架代碼:java
const Koa = require('koa'); const app = new Koa(); app.use(statics( path.join(__dirname,staticPath) )); app.use(statics('.')); app.use(bodyParser()); app.listen(9000); //後端接聽9000端口
2.前端引入靜態文件,這樣react,build好的文件直接和後端連接起來react
const statics = require('koa-static'); //使用koa-static const staticPath = './build'; app.use(statics( path.join(__dirname,staticPath) )); app.use(statics('.'));
3.get 和put 方法設置git
app.use(async(ctx, next) => { await next(); ctx.response.type = 'text/html'; // ctx.response.body = '<h1>Hello,koa2222!</h1>'; // console.log('ctx use',ctx.url,ctx.method); if(ctx.method === 'GET'){ //當請求時GET請求時 ctx.body =ctx.response.body; }else if(ctx.url==='/' && ctx.method === 'POST'){ //當請求時POST請求時 ctx.body=await parsePostData(ctx); }else{ //其它請求顯示404頁面 ctx.body='<h1>404!</h1>'; } }); function parsePostData( ctx ) { return new Promise((resolve, reject) => { try { let postdata = ""; ctx.req.addListener('data', (data) => { postdata += data }) ctx.req.addListener("end",function(){ let parseData = parseQueryStr( postdata ); resolve( parseData ) }) } catch ( err ) { reject(err) } }) } function parseQueryStr( queryStr ) { let queryData = {}; let queryStrList = queryStr.split('&'); console.log( queryStrList ); for ( let [ index, queryStr ] of queryStrList.entries() ) { let itemList = queryStr.split('='); queryData[ itemList[0] ] = decodeURIComponent(itemList[1]) } return queryData }
4.跨域設置github
const cors = require('koa-cors'); app.use(cors());
5.圖片上傳api實現json
router.post('/upload', async(ctx, next) => { //提交圖片接口 var form = new multiparty.Form({uploadDir: './files/'}); // 上傳完成後處理 form.parse(ctx.req, function(err, fields, files) { //fields裏有前端append的參數 if (err) { throw err; } else { //form.append ()的值在fields中 processImg(ctx.req, ctx.res, files,fields).then(function(data) { console.log('hshsh') // 設置跨域 // allowCross(ctx); // res.json({ // res: JSON.parse(data.filesTmp), // relPath: data.relPath, // }) }).catch(function(err) { console.log(err) }); } }); }); function processImg(req, res, files,fields) { return new Promise(function(resolve, reject) { const _img = files.filedata[0]; const uploadedPath = _img.path; const originalFilename = _img.originalFilename; let dstPath = './imgs/'+ originalFilename; // console.log('dstPath',dstPath); // (目前的路徑,重命名後的路徑)重命名 fs.rename(uploadedPath, dstPath, function(err) { if (err) { reject(err) } else { console.log('rename ok!'); } }); }); }
前端:
1.material-ui
地址:https://material-ui.com/ 它是React組件,實現了谷歌Material Design設計規範。世界上最流行的React界面框架。
2.圖片是file類型,須要轉數組Array.prototype.slice.call
;
3.當上傳圖片的時候,若是還須要從前端日後端傳參數能夠使用form.append("filedata", file);
的方法
後端:
1.後端的form.parse
方法的fields
裏有前端append
的參數;
2.跨域使用koa-cors
;
3.上傳的圖片名字不是圖片自己的名字,能夠fs.rename
來從新命名
4.get
和put
方法須要區分,能夠使用上文中的代碼。
5.koa-static
能夠將react 中build後的文件同後端連接起來後端