talk is cheap show me the code

The resources

  1. element-ui
  2. Vue front end (Element-UI), Express back end to upload pictures to Qiuniuyun

The front-end component

  1. The detailed style configuration can be found on the Element-UI website

  2. The first configuration: upload the image directly after selecting it (action is the address of the server, http-Request is the operation that intercepts the request before uploading it to the server) :

    <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"> Only JPG/PNG files with a maximum size of 500KB </div> </el-upload>Copy the code

    A reference to the uploadImage() function configuration (mainly rename the image name, I used Mongoose Types to generate a unique ObjectId to rename the image, or use a timestamp, etc.) :

    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)
      })
    },
    Copy the code

    Note that uploading images to a cross-domain server requires cross-domain processing, so we can use ‘/ API ‘instead of the server address. In Vue, we can modify config/index.js:

    proxyTable: {
        '/api': {
            target: 'https://example.com'.// Interface domain name
            secure: false.// If the interface is HTTPS, you need to set this parameter
            changeOrigin: true.// This parameter is required if the interface is cross-domain
            pathRewrite: {'^/api': ' '}}},Copy the code

    In Nuxt we can configure nuxt.config.js:

    modules: ['@nuxtjs/axios'.'@nuxtjs/proxy'].proxy: [
        '/api',
        {
            target: 'https://example.com'.pathRewrite: {'^/api': '/'}}].Copy the code
  3. Another configuration: upload to the server after clicking the upload button (mainly set the :auto-upload of the upload component to false). To implement image preview you can add a handler :on-change=”handleSuccess” :

    handleSuccess(res, files) {
        this.fileList = [];// Because I only select one image per upload, so clear
        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;/ / save the imageFile
            this.fileList.push({name: name, url: imageUrl}); }},Copy the code

    UploadImage () function uploadImage()

    try {
        // Obtain the upload certificate token
        let uptoken = await this.$store.dispatch('getUploadToken');
        const formdata = new FormData();
        formdata.append('file'.this.imageFile.raw);
        formdata.append('token', uptoken);// Add credentials
        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);
        }
    Copy the code

    So if we want to upload, we can call uploadImage asynchronously to return the path of the image that was uploaded

The backend configuration

  1. To avoid exposing the key, the voucher token should be obtained from the back end:
    const qiniu = require('qiniu')
    //util/onfig/qiniu.js //util/onfig/qiniu.js //util/onfig/qiniu.js
    import {accessKey, secretKey} from '.. /util/config/qiniu'
    For example, I added the following function to the Vuex Store action
    getUploadToken() {
        const mac = new qiniu.auth.digest.Mac(accessKey, secretKey);
        const options = {
            scope: 'xxxxx'.// You are in the seven niuyun space name
        };
        const putPolicy = new qiniu.rs.PutPolicy(options);
        return putPolicy.uploadToken(mac);
    },
    Copy the code
  2. Upload to local folder, Express + Multiparty configuration image upload server:
    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];// Since element-UI uploads one image at a time, consider taking out the first one
        let newPath = config.imagePath + newName;
        let originalPath = files.file[0].path;
        try {
            fs.existsSync(originalPath);// Whether the local image path exists
            fs.renameSync(originalPath,newPath);// Rename, preferably using renameSync force-name
            return res.status(200).json({name: newName, url: config.imageURL + newName});
        } catch (error) {
            return res.status(500).json({message: "upload image failed: "+ error}); }}); });Copy the code

Some difficulties

If the upload fails, check whether the formdata in the request is empty. The other is cross-domain configuration.


A small record, welcome to comment