ps:以为有帮助的同窗点个赞或者github star 在此谢过react
批量上传和下载webpack
mongoose数据库操做ios
增删查git
webpack4部分优化配置github
jwt登陆控制、路由鉴权web
tips:批量下载须要使用引入archiver第三方包将多个文件打包成一个压缩文件mongodb
//此处分为文件和图片两个接口 router.get('/downloadFile/:name',//文件 async ctx => { ctx.set('Content-disposition', `attachment;filename=${ctx.params.name}`); const paths = `src/assets/upload/files/${ctx.params.name}` const data = fs.createReadStream(paths) // 发送路径文件内容的文件 ctx.body = data } ).get('/downloadImg/:name',//图片 async ctx => { ctx.set('Content-disposition', `attachment;filename=${ctx.params.name}`); const paths = `src/assets/upload/imgs/${ctx.params.name}`; ctx.attachment(paths); await send(ctx, paths); } ) //批量下载 router.get('/batchDownload', async ctx => { const list = [{ name: '1.jpg', path: 'src/assets/upload/imgs/1.jpg' }, { name: '1.csv', path: 'src/assets/upload/files/1.csv' }, { name: '2.png', path: 'src/assets/upload/imgs/2.png' }];//name为压缩文件内生成的文件名称,path为要下载的文件路径 const zipName = 'download.zip';//自定义生成的压缩文件名称 const zipPath = `src/assets/download/${zipName}`;//自定义生成的压缩文件路径 const zipStream = fs.createWriteStream(zipPath); const zip = archiver('zip'); zip.pipe(zipStream); for (let i = 0; i < list.length; i++) { // 添加单个文件到压缩包 zip.append(fs.createReadStream(list[i].path), { name: list[i].name }) } await zip.finalize(); ctx.attachment(zipPath); await send(ctx, zipPath); } )
//此处同Koa app.get('/downloadFile/:name', (req, res) => { const filePath = `src/assets/upload/files/${req.params.name}` if (fs.existsSync(filePath)) { res.download(filePath) } else { res.json({ err: 'file is not exist', success: false }) } } ).get('/downloadImg/:name', (req, res) => { const filePath = `src/assets/upload/imgs/${req.params.name}` if (fs.existsSync(filePath)) { res.download(filePath) } else { res.json({ err: 'file is not exist', success: false }) } } ).get('/batchDownload', async (req, res) => { const list = [{ name:'1.jpg',path: 'src/assets/upload/imgs/1.jpg' }, { name:'1.csv',path: 'src/assets/upload/files/1.csv' }, { name:'2.png',path: 'src/assets/upload/imgs/2.png' }]; const zipName = 'download.zip'; const zipPath = `src/assets/download/${zipName}`; const zipStream = fs.createWriteStream(zipPath); const zip = archiver('zip'); zip.pipe(zipStream); for (let i = 0; i < list.length; i++) { // 添加单个文件到压缩包 zip.append(fs.createReadStream(list[i].path), { name: list[i].name }) } await zip.finalize(); setTimeout(() => { res.download(zipPath) }, 0); } )
//接收post请求须要先处理options请求 app.use( async (ctx, next) => { if (ctx.request.method === "OPTIONS") { ctx.response.status = 200 ctx.set('Access-Control-Allow-Origin', ctx.request.headers.origin) ctx.set("Access-Control-Max-Age", 24 * 60 * 60 * 1000); ctx.set("Access-Control-Allow-Methods", 'GET,POST,OPTIONS,DELETE,PUT'); ctx.set("Access-Control-Allow-Headers", 'Origin,Content-Type,Authorization,Accept,X-Custom-Header,anonymous,X-Requested-With') ctx.body = '' } else { await next() } } ) //上传 router.post('/upload', ctx => { try { const files = ctx.request.files.file files.length ? files.forEach(file => fs .createReadStream(file.path) .pipe(fs.createWriteStream(`${file.type.indexOf('image') >= 0 ? 'src/assets/upload/imgs' : 'src/assets/upload/files'}/${file.name}`)) ) : fs .createReadStream(files.path) .pipe(fs.createWriteStream(`${files.type.indexOf('image') >= 0 ? 'src/assets/upload/imgs' : 'src/assets/upload/files'}/${files.name}`)) ctx.body = '上传成功' } catch (e) { ctx.body = '上传失败' } } )
//处理options app.all('*', (req, res, next) => { if (req.method === "OPTIONS") { res.status(200) res.end() } else { next() } } ).post('/upload', upload.any(), (req, res, next) => { try { const files = req.files console.log(files) files.length ? files.forEach(file => fs .createReadStream(file.path) .pipe(fs.createWriteStream(`${file.mimetype.indexOf('image') >= 0 ? 'src/assets/upload/imgs' : 'src/assets/upload/files'}/${file.originalname}`)) ) : fs .createReadStream(files.path) .pipe(fs.createWriteStream(`${files.mimetype.indexOf('image') >= 0 ? 'src/assets/upload/imgs' : 'src/assets/upload/files'}/${files.originalname}`)) res.json({ err: 'upload success', success: false }) } catch (e) { res.json({ err: 'upload failed', success: false }) } } )
分为两个文件 connect.js链接数据库,db.js导出mongodb的自定义数据模型数据库
const mongoose = require('mongoose') mongoose.Promise = global.Promise mongoose.connect('mongodb://用户名:密码@ds145093.mlab.com:45093/用户名', { useNewUrlParser: true }, (err, info) => { if (err) throw 'mongodb connect failed' console.log('mongodb connect success') } )
require('./connect') const mongoose = require('mongoose'); const Schema = mongoose.Schema; const todoSchema = new Schema({ name: String, isDoing: Boolean, createDate: Date, }, {versionKey: false}) const Todo = mongoose.model('Todo', todoSchema) exports.Todo=Todo;
//须要引入koa-body const koaBody = require('koa-body') //查询全部记录 app.get('/todoList', async ctx => { try { let data = await Todo.find({}) ctx.body = { data, success: true } } catch (e) { ctx.body = { data: [], success: false } } }, ).get('/todoList/:name',//模糊查询单一记录 async ctx => { const params = { name: { $regex: new RegExp(`${ctx.params.name}`) } } try { let data = await Todo.find(params) ctx.body = { data, success: true } } catch (e) { ctx.body = { data: [], success: false } } } ).post('/todoList', koaBody(),//新增记录 async ctx => { const todo = new Todo({ ...ctx.request.body }) try { let data = await todo.save() ctx.body = { data, success: true } } catch (err) { ctx.body = { data: { err }, success: false } } } ).del('/todoList/:name',//删除记录 async ctx => { const params = { name: ctx.params.name } try { let data = await Todo.findOneAndDelete(params) ctx.body = { data, success: true } } catch (err) { ctx.body = { data: { err }, success: false } } } )
//查询全部记录 app.get('/todoList', async (req, res, next) => { try { let data = await Todo.find({}) res.json({ data, success: true }) } catch (e) { res.json({ data: [], success: false }) } }, ).get('/todoList/:name',//模糊查询记录 async (req, res, next) => { const params = { name: { $regex: new RegExp(`${req.params.name}`) } } try { let data = await Todo.find(params) res.json({ data, success: true }) } catch (e) { res.json({ data: [], success: false }) } } ).post('/todoList',//新增记录 async (req, res, next) => { const todo = new Todo({ ...req.body }) try { let data = await todo.save() res.json({ data, success: true }) } catch (err) { res.json({ data: { err }, success: false }) } } ).delete('/todoList/:name',//删除记录 async (req, res, next) => { const params = { name: req.params.name } try { let data = await Todo.findOneAndDelete(params) res.json({ data, success: true }) } catch (err) { res.json({ data: { err }, success: false }) } } )
//dll.js const path = require('path') const webpack = require('webpack') module.exports = { entry: { vendor: [ 'react', 'react-dom', 'react-router-dom', 'immutable', 'antd', 'axios', ], }, output: { filename: '[name].dll.js', path: path.resolve(__dirname, '../public'), library: '[name]_library', }, plugins: [ new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify('production') }), new webpack.DllPlugin({ path: path.resolve(__dirname, '../public','[name]-manifest.json'), name: '[name]_library', context: __dirname }) ], }
optimization: { splitChunks: { chunks: 'all', name: false, cacheGroups: { commons: { name: 'commons', priority: 10, chunks: 'initial' } }, } }
//引入happypack const HappyPack = require('happypack') new HappyPack({ id: 'jsx', threads: 4, loaders: ['babel-loader?presets[]=react,presets[]=latest&compact=false'], })
//引入react-loadable import Loadable from 'react-loadable' const MyLoadingComponent = ({ isLoading, error }) => { return '' } const Nav = Loadable({ loader: () => import(/* webpackChunkName: "Nav" */'../components/Nav'),//注释是为了让webpack打包出来的文件以路由为名 loading: MyLoadingComponent })