talk is cheap show me the code
参考资料
前端组件
-
具体的样式配置可以见element-ui的官网
-
第一种配置:选择图片后直接上传(action是服务器地址,http-request是上传到服务器前拦截request进行处理的操作):
<el-upload class="upload-demo" ref="upload" :action=domain :http-request=uploadImage :file-list="fileList" list-type="picture-card" :before-upload="beforeUpload" multiple> <i class="el-icon-plus"></i> <div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kb</div> </el-upload>一个参考的uploadImage()函数配置(这里主要需要重命名图片名,我使用mongoose的Types生成一个唯一的ObjectId来进行重命名,也可以使用时间戳等方式):
async uploadImage(req) { const config = { headers: {'Content-Type': 'multipart/form-data'} }; let filetype = '' if (req.file.type === 'image/png') { filetype = 'png' } else { filetype = 'jpg' } const keyName = this.bucket + "-" + Types.ObjectId().toString() + '.' + fileType; const formdata = new FormData(); formdata.append('file', req.file); formdata.append('key', keyName); axios.post('/api/uploadImage', formdata, config) .then(res => { this.fileList.push({ name: res.data.name, url: res.data.url, }); console.log('image upload succeed.'); }) .catch(err => { console.log(err.message) }) },注意到:我们如果将图片上传到一个跨域服务器是需要进行跨域处理的,后面我们就可以使用'/api'代替服务器地址。
① 在Vue中我们可以修改config/index.js:proxyTable: { '/api': { target: 'https://example.com', // 接口的域名 secure: false, // 如果是https接口,需要配置这个参数 changeOrigin: true, // 如果接口跨域,需要进行这个参数配置 pathRewrite: {'^/api': ''} } },② 在Nuxt中我们可以配置nuxt.config.js:
modules: ['@nuxtjs/axios','@nuxtjs/proxy'], proxy: [ '/api', { target: 'https://example.com', pathRewrite: {'^/api': '/'} } ], -
另一种配置:点击上传按钮后才上传到服务器(主要将上传组件的
:auto-upload设置为false)。如果要实现图片预览可以添加一个处理函数:on-change="handleSuccess":handleSuccess(res, files) { this.fileList = [];//因为我这里每次上传只选择一张图片,所以清空 let file = files[files.length - 1]; let name = file.name; if(this.beforeUpload(file.raw)) { let imageUrl = window.URL.createObjectURL(file.raw); this.imageFile = file;//保存imageFile this.fileList.push({name: name, url: imageUrl}); } },上传到七牛云可以对uploadImage()函数进行修改:
try { //获取上传凭证token let uptoken = await this.$store.dispatch('getUploadToken'); const formdata = new FormData(); formdata.append('file', this.imageFile.raw); formdata.append('token', uptoken);//添加凭证 formdata.append('key', keyName); return new Promise((resolve, reject) => { axios.post('/upQiniu', formdata, config).then(res => { this.imageUrl = 'http://' + this.qiniuaddr + '/' + res.data.key; this.fileList = []; this.imageFile = null; resolve(this.imageUrl); }); }); } catch (e) { console.log('post failed!' + e.message); }后面我们要上传可以直接调用uploadImage函数异步返回图片上传后的路径
后端配置
- 上传到七牛云,为了避免暴露密钥,凭证token应该从后端获取:
const qiniu = require('qiniu') //util/onfig/qiniu.js中放置七牛云的访问key和密钥 import {accessKey, secretKey} from '../util/config/qiniu' //例如我在Vuex Store的action中添加了以下函数 getUploadToken() { const mac = new qiniu.auth.digest.Mac(accessKey, secretKey); const options = { scope: 'xxxxx',//你在七牛云的空间名字 }; const putPolicy = new qiniu.rs.PutPolicy(options); return putPolicy.uploadToken(mac); }, - 上传到本地文件夹,express+multiparty配置图片上传服务器:
router.post('/uploadImage', async(req, res, next) => { var form = new multiparty.Form(); form.uploadDir = config.imagePath; form.maxFieldsSize = 2 * 1024 * 1024; var newName; await form.parse(req, (err, fields, files) => { if(err) { return res.status(500).json({message: "upload image failed: " + err}); } newName = fields.key[0];//因为element-ui每次上传一张图片,所以这里考虑取出第一个即可 let newPath = config.imagePath + newName; let originalPath = files.file[0].path; try { fs.existsSync(originalPath);//本地图片路径是否存在 fs.renameSync(originalPath,newPath);//重命名,这里最好使用renameSync强制命名 return res.status(200).json({name: newName, url: config.imageURL + newName}); } catch (error) { return res.status(500).json({message: "upload image failed: " + error}); } }); });
一些难点
一个是上传的formdata配置,注意配置config,如果上传失败检查request中的formdata是否为空;另一个是跨域配置。
一个小记录,欢迎指教