ionic3 上傳圖片、壓縮圖片到阿里雲 服務端簽名後直傳

weixin_34377065發表於2018-06-08

1.為什麼用plupload.js
首先使用這個plupload是因為我採用的 【阿里雲 服務端簽名後直傳】,使用的是這個方法。
放上阿里雲的地址:https://help.aliyun.com/document_detail/31926.html?spm=a2c4g.11174283.6.634.PYDsbd

2.關於plupload.js
大致有以下幾個引數:

      runtimes: 'html5,flash,silverlight,html4', // 用來指定上傳方式
      browse_button: 'selectfiles', // 觸發檔案選擇對話方塊的DOM元素
      multi_selection: false, // 是否可以在檔案瀏覽對話方塊中選擇多個檔案,true為可以,false為不可以
      container: document.getElementById('container'), // 用來指定Plupload所建立的html結構的父容器
      url: '*******', // 伺服器端接收和處理上傳檔案的指令碼地址
      filters: {
        mime_types: [ // 用來限定上傳檔案的型別
          { title: "Image files", extensions: "jpg,jpeg,gif,png,bmp" },
        ],
        max_file_size: '10mb', // 用來限定上傳檔案的大小
        prevent_duplicates: true, // 是否允許選取重複的檔案,為true時表示不允許,為false時表示允許,預設為false。如果兩個檔案的檔名和大小都相同,則會被認為是重複的檔案
      },
      resize: { // 壓縮
        width:1000,
        height:800,
        crop: false,
        quality: 90,
        preserve_headers: false
      },

大致的事件:

Init // 當Plupload初始化完成後觸發
PostInit // 當Init事件發生後觸發
FilesAdded // 當檔案新增到上傳佇列後觸發
BeforeUpload // 當佇列中的某一個檔案正要開始上傳前觸發
UploadProgress // 顯示上傳進度
FileUploaded  // 當佇列中的某一個檔案上傳完成後觸發
Error  // 錯誤

以上是我用到的,大家可以根據自己的需求去新增。具體可參考部落格:https://www.cnblogs.com/2050/p/3913184.html
寫的很詳細了,我也是參考這個部落格的,對plupload有了進一步認識。

3.使用
html:

<img class="photo" src="{{photourl}}" alt="">
<div id="ossfile" class="ossfile"></div>
<div id="container" class="upload_btn">
     <button ion-button icon-only id="selectfiles">選擇檔案</button>
     <button ion-button icon-only id="postfiles">開始上傳</button>
</div>

ts:

set_upload_param(up, filename) {
    let token = ********;
    ***********.subscribe((body: any) => {
    // 這裡是我向後臺傳送的請求 獲取到需要上傳給 阿里雲的資料
        let new_multipart_params = {
          'key': dir + '${filename}',
          'policy':policy,
          'OSSAccessKeyId':accessid,
          'success_action_status': '200', //讓服務端返回200,不然,預設會返回204
          'signature': signature,
          'x-oss-object-acl': 'public-read'
        };
        up.setOption({
          'url': host,
          'multipart_params': new_multipart_params
        });
        up.start();
      }
    })
  }

  uploadImg() {
  // 這裡需要注意 this 的指向問題
    let that = this;
    this.uploader = new plupload.Uploader({
      runtimes: 'html5,flash,silverlight,html4',
      browse_button: 'selectfiles', 
      multi_selection: false, 
      container: document.getElementById('container'), 
      url: '*******', 
      filters: {
        mime_types: [ 
          { title: "Image files", extensions: "jpg,jpeg,gif,png,bmp" },
        ],
        max_file_size: '10mb', 
        prevent_duplicates: true, 
      },
      resize: { 
        crop: false,
        quality: 90,
        preserve_headers: false
      },

      init: {
        PostInit: function () {
          document.getElementById('postfiles').onclick = function () {
            that.set_upload_param(that.uploader, '');
            return false;
          };
        },

        FilesAdded: function (up, files) {
          document.getElementById('ossfile').innerHTML = '';
          plupload.each(files, function (file) {
            document.getElementById('ossfile').innerHTML += '<div id="' + file.id + '">' + '(' + file.name + ')<b></b>'
              + '<div class="progress"><div class="progress-bar" style="width: 0%"></div></div>'
              + '</div>';
          });

          // 這裡【重點】:獲取圖片的原始尺寸來進行計算 壓縮的尺寸
          // 我這裡設定的寬1000,高800 
          let image = new Image();
          let reader = new FileReader();
          reader.onload = (readerEvent: any) => {
            image.onload = () => {
              let originalWidth = image.width; // 原始圖片的寬
              let originalHeight = image.height; // 原始圖片的高
              if (originalWidth >= 1000) {
                that.uploader.settings.resize.width = 1000;
                that.uploader.settings.resize.height = Math.floor(originalHeight * (that.uploader.settings.resize.width / originalWidth));
                if (that.uploader.settings.resize.height > 800) {
                  that.uploader.settings.resize.width = Math.floor(that.uploader.settings.resize.width * (800 / that.uploader.settings.resize.height));
                  that.uploader.settings.resize.height = 800;
                }
              }
              else if (originalHeight > 800) {
                that.uploader.settings.resize.height = 800;
                that.uploader.settings.resize.width = Math.floor(originalWidth * (that.uploader.settings.resize.height / originalHeight));
              }
              else {
                that.uploader.settings.resize.width = originalWidth;
                that.uploader.settings.resize.height = originalHeight;
              }
            };
            image.src = readerEvent.target.result;
          };
          reader.readAsDataURL(files[0].getNative());
        },

        BeforeUpload: function (up, file) {
          that.set_upload_param(up, file.name);
        },

        UploadProgress: function (up, file) {
          var d = document.getElementById(file.id);
          d.getElementsByTagName('b')[0].innerHTML = '<span>' + file.percent + "%</span>";
          var prog = d.getElementsByTagName('div')[0];
          var progBar = prog.getElementsByTagName('div')[0]
          progBar.style.width = 2 * file.percent + 'px';
          progBar.setAttribute('aria-valuenow', file.percent);
        },

        FileUploaded: function (up, file, info) {
          if (info.status == 200) {
            that.appStatus.infoMsg('上傳成功');
            // 這一步是 上傳成功後,清除進度條
            document.getElementById('ossfile').innerHTML = '';
          }
          else if (info.status == 203) {
            console.log('上傳到OSS成功,但是oss訪問使用者設定的上傳回撥伺服器失敗');
            console.log('失敗原因是:' + info.response);
          }
          else {
            console.log('失敗原因是:' + info.response);
          }
        },

        Error: function (up, err) {
          if (err.code == -600) {
            that.appStatus.infoMsg("選擇的檔案太大了!")
          }
          else if (err.code == -601) {
            that.appStatus.infoMsg("選擇的上傳檔案型別不對!")
          }
          else if (err.code == -602) {
            that.appStatus.infoMsg("這個檔案已經選擇過一遍了!")
          }
          else {
            console.log(err.response)
          }
        }
      }
    });
    this.uploader.init();
  }

【重點】:

  1. this的指向問題
  2. resize的寬高動態賦值需要是:uploader.settings.resize.width 、uploader.settings.resize.height
  3. resize只給寬,比如
    resize: {
    width:800,
    crop: false,
    quality: 90,
    preserve_headers: false
    },
    這個能實現壓縮,圖片體積可以壓縮,寬高可以不進行剪裁 同比例縮小。圖片大於800進行壓縮,小於不壓縮。我的需求是限定了高,所以要進行計算。
  4. 案例上的進度條是 同時存在多個。我的需求是 只顯示一個,成功後消失。具體程式碼是:
FilesAdded: function (up, files) {
          document.getElementById('ossfile').innerHTML = '';
          plupload.each(files, function (file) {
            document.getElementById('ossfile').innerHTML += '<div id="' + file.id + '">' + '(' + file.name + ')<b></b>'
              + '<div class="progress"><div class="progress-bar" style="width: 0%"></div></div>'
              + '</div>';
          });
}

FileUploaded: function (up, file, info) {
          if (info.status == 200) {
            that.appStatus.infoMsg('上傳成功');
            // 這一步是 上傳成功後,清除進度條
            document.getElementById('ossfile').innerHTML = '';
          }
}

這個實現了我的需求,還有許多不足之處,大家可以做個參考!

最後給大家看下我的頁面效果:


6544492-428d389b67883b8e.png
image.png

相關文章