多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
## 技术栈 koa2 + react16.8 github 地址[链接](https://github.com/freya0608/react-imgUpload.git) ## 项目步骤 * ### 前端开发 1.创建`react app` `yarn create react-app my-app` 2.用`material-ui`编写页面,代码如下 ``` <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) } } ~~~ * ### 后端开发 1.koa搭建框架代码: ``` const Koa = require('koa'); const app = new Koa(); app.use(statics( path.join(__dirname,staticPath) )); app.use(statics('.')); app.use(bodyParser()); app.listen(9000); ``` 2.前端引入静态文件,这样react,build好的文件直接和后端链接起来 ~~~ const statics = require('koa-static'); const staticPath = './build'; app.use(statics( path.join(__dirname,staticPath) )); app.use(statics('.')); ~~~ 3.get 和put 方法设置 ~~~ 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.跨域设置 ~~~ const cors = require('koa-cors'); app.use(cors()); ~~~ 5.图片上传api实现 ~~~ router.post('/upload', async(ctx, next) => { //提交图片接口 var form = new multiparty.Form({uploadDir: './files/'}); // 上传完成后处理 form.parse(ctx.req, function(err, fields, files) { 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!'); } }); }); } ~~~