Element: [Upload] 希望增加图片压缩功能

Created on 15 Nov 2016  ·  16Comments  ·  Source: ElemeFE/element

ElementUI version


1.0.0

OS/Browers version

Vue version


2.0.3

Reproduction Link



Steps to reproduce

What is Expected?

What is actually happening?

upload discussion feature request

Most helpful comment

支持,我也需要。等不及已經先自己寫了,給大家參考,以下是部份代碼,有點粗糙但是...可以work

ps. 此例中,我是按照自己的需求,客製化上傳至aws s3,不適用el-button的action路徑。建議只看壓縮圖片的部份。

// component.vue
    beforeUpload(file) {                       // el-upload的鉤子
      this.isUploading = true                  // 讓el-upload button顯示loading狀態

      // 產生縮圖後,上傳原圖及縮圖
      helper.resizeAndUploadImage(file).then((filename,thumbFilename) => {
        this.product.pictures.push(filename);
      })
      .catch((err) => {
        alert(err);
      })
      .then(() => {
        this.isUploading = false
      });
      return false                               //取消el-upload上傳,使用客製化上傳
    }

壓縮圖片,必須用到canvas。

// helper.js

  // 從canvas轉出檔案
   dataURItoBlob(dataURI) {
      var binary = atob(dataURI.split(',')[1]);
      var array = [];
      for(var i = 0; i < binary.length; i++) {
          array.push(binary.charCodeAt(i));
      }
      return new Blob([new Uint8Array(array)], {type: 'image/jpeg'});
  },

  //圖片壓縮
  preprocessUploadImageFile(file, callback) {                  
    const self = this
    const ext = this.getExt(file.name);
    var reader = new FileReader();

    reader.onload = function (readerEvent) {
      var image = new Image();
      image.onload = function (imageEvent) {
        var canvas = document.createElement('canvas'),
            width = image.width,
            height = image.height,
            ratio =  Math.sqrt(THUMB_IMAGE_TARGET_SIZE / file.size);
        width *= ratio;
        height *= ratio;
        canvas.width = width;
        canvas.height = height;
        canvas.getContext('2d').drawImage(image, 0, 0, width, height);
        var dataUrl = canvas.toDataURL('image/jpeg');
        var blobData = self.dataURItoBlob(dataUrl);
        callback(blobData)
      }
      image.src = readerEvent.target.result;
    }
    reader.readAsDataURL(file);
  },
  resizeAndUploadImage(file) {
    return new Promise( (ok, fail) => {
      if(file.size > IMAGE_TARGET_SIZE) return fail("圖片尺寸太大");
      if (!file.type.match(/image.*/)) return fail("file must be image");

      this.preprocessUploadImageFile(file, (resizedImageBlob) => {
        const ext = this.getExt(file.name);
        var nameObject = this.getRandomeFileNames(ext);
        this.uploadS3(nameObject.thumbname, resizedImageBlob).then( (data) => {
          this.uploadS3(nameObject.name, file).then((data) => {
            ok(nameObject.name,nameObject.thumbname);
          })
        })
        .catch((err) => fail(err))
      });
    })

  },

All 16 comments

问题描述请再详细一点。

需要在上传到服务器前,前端将图片压缩到一定大小

action="/redwood/sys/Common/uploadFile.do"
:multiple="true"
:show-upload-list="false"
style="display:inline-block; width: auto; margin-bottom: 8px;"
:before-upload="beforeUpload"
:on-success="handleSuccess"
:on-error="handleError"
>
点击上传
el-upload提供一个类似这样的配置参数,如compress = '{ width: xxx, height: xxx, quality: 0.8 }'

@Leopoldthecoder 如上楼所描述

后面会考虑添加,先立一个 1.1 版本会添加的 Milestone 吧。

支持,我也需要。等不及已經先自己寫了,給大家參考,以下是部份代碼,有點粗糙但是...可以work

ps. 此例中,我是按照自己的需求,客製化上傳至aws s3,不適用el-button的action路徑。建議只看壓縮圖片的部份。

// component.vue
    beforeUpload(file) {                       // el-upload的鉤子
      this.isUploading = true                  // 讓el-upload button顯示loading狀態

      // 產生縮圖後,上傳原圖及縮圖
      helper.resizeAndUploadImage(file).then((filename,thumbFilename) => {
        this.product.pictures.push(filename);
      })
      .catch((err) => {
        alert(err);
      })
      .then(() => {
        this.isUploading = false
      });
      return false                               //取消el-upload上傳,使用客製化上傳
    }

壓縮圖片,必須用到canvas。

// helper.js

  // 從canvas轉出檔案
   dataURItoBlob(dataURI) {
      var binary = atob(dataURI.split(',')[1]);
      var array = [];
      for(var i = 0; i < binary.length; i++) {
          array.push(binary.charCodeAt(i));
      }
      return new Blob([new Uint8Array(array)], {type: 'image/jpeg'});
  },

  //圖片壓縮
  preprocessUploadImageFile(file, callback) {                  
    const self = this
    const ext = this.getExt(file.name);
    var reader = new FileReader();

    reader.onload = function (readerEvent) {
      var image = new Image();
      image.onload = function (imageEvent) {
        var canvas = document.createElement('canvas'),
            width = image.width,
            height = image.height,
            ratio =  Math.sqrt(THUMB_IMAGE_TARGET_SIZE / file.size);
        width *= ratio;
        height *= ratio;
        canvas.width = width;
        canvas.height = height;
        canvas.getContext('2d').drawImage(image, 0, 0, width, height);
        var dataUrl = canvas.toDataURL('image/jpeg');
        var blobData = self.dataURItoBlob(dataUrl);
        callback(blobData)
      }
      image.src = readerEvent.target.result;
    }
    reader.readAsDataURL(file);
  },
  resizeAndUploadImage(file) {
    return new Promise( (ok, fail) => {
      if(file.size > IMAGE_TARGET_SIZE) return fail("圖片尺寸太大");
      if (!file.type.match(/image.*/)) return fail("file must be image");

      this.preprocessUploadImageFile(file, (resizedImageBlob) => {
        const ext = this.getExt(file.name);
        var nameObject = this.getRandomeFileNames(ext);
        this.uploadS3(nameObject.thumbname, resizedImageBlob).then( (data) => {
          this.uploadS3(nameObject.name, file).then((data) => {
            ok(nameObject.name,nameObject.thumbname);
          })
        })
        .catch((err) => fail(err))
      });
    })

  },

@red010182 不是不支持 promise对象吗?你这样写,图片并不会上传到action的路径

beforUpload拿到的一直是false

@spademan 此例中,我是按照自己的需求,客製化上傳至aws s3,不適用el-upload的action路徑。建議只看壓縮圖片的部份。

我明白,我用的lrz也是拦截beforeupload的参数 然后自己在lrz的回调里面触发request

直接把plupload搬过来搞定

这个是沉了吗

同问,这个是沉了吗?

同问,这个是沉了吗?

移到需求池里了,将关闭这个 issue 。

2019年5月15日,请问一下目前这个需求怎么解决?

同问,这个需求现在实现了吗?

Was this page helpful?
0 / 5 - 0 ratings