鍍金池/ 問答/HTML/ 做H5頁面,調用相冊圖片文件太大,怎么實現(xiàn)上傳縮略圖或者壓縮圖

做H5頁面,調用相冊圖片文件太大,怎么實現(xiàn)上傳縮略圖或者壓縮圖

做H5頁面,調用相冊圖片文件太大,怎么實現(xiàn)上傳縮略圖或者壓縮圖

回答
編輯回答
痞性

canvas壓縮下。有現(xiàn)成插件比如localResizeIMG

2018年1月26日 11:21
編輯回答
礙你眼

可以利用canvas對圖片進行壓縮之后再上傳。或者你可以直接利用webuploader這個庫

2017年5月28日 13:20
編輯回答
風畔

趁著中午,大致代碼的我寫一下,供參考:

// 上傳函數(shù)
function upload(e) {
    var file = e.target.files[0];
    if (!file) return; // 未上傳
    var orientation; // 圖片上傳的角度,解決
    /**
    * 利用exif.js解決ios手機上傳豎拍照片旋轉90度問題
    * 詳見  http://code.ciaoca.com/javascript/exif-js/
    */ 
    EXIF.getData(file, function () { // 獲取照片方向角屬性,用戶旋轉控制  
      orientation = EXIF.getTag(this, 'Orientation');
    });
    var reader = new FileReader(); // 讀取文件
    reader.onload = function () {
      getImgData(this.result, orientation, function (result) {
        var img = new Image();
        img.src = result;
        // 如果圖片大小小于200kb,則直接上傳
        if (result.length <= that.minSize) {
          ajaxUpload(result, file.type, file.name); // 調用上傳接口函數(shù)
          img = null;
          return;
        }
        // 圖片加載完畢之后進行壓縮,然后上傳
        if (img.complete) {
          callback();
        } else {
          img.onload = callback;
        }
        function callback () {
          var data = compress(img);
          // 文件上傳
          ajaxUpload(data, file.type, file.name);
          img = null;
        }
      })
    }
    reader.readAsDataURL(file);
}

/**
 * 圖片上傳,將base64的圖片轉成二進制對象,塞進formdata上傳
 * @param {*} basestr
 * @param {*} type
 */
function ajaxUpload (basestr, type, name) {
  var text = window.atob(basestr.split(',')[1]);
  var buffer = new Uint8Array(text.length);
  for (var i = 0; i < text.length; i++) {
    buffer[i] = text.charCodeAt(i);
  }
  var blob = getBlob([buffer], type);
  var xhr = new XMLHttpRequest();
  var formdata = getFormData();
  formdata.append('multipartFile', blob, name)
  // append 追加還追加其他參數(shù)
  xhr.open('post', '請求的url')
  xhr.onreadystatechange = function () {
      if (xhr.readyState === 4 && xhr.status === 200) {
          var jsonData = JSON.parse(xhr.responseText)
          // 接口返回的 json 數(shù)據(jù) 自行解析
      }

      if (xhr.status !== 200) {
        // 通信失敗
     }
  }
  xhr.send(formdata)
}

/**
   * 使用canvas對大圖片進行壓縮
   * @param {img} 圖片
   */
function compress (img) {
    // 用于壓縮圖片的canvas
    var canvas = document.createElement('canvas');
    var ctx = canvas.getContext('2d');
    // 瓦片canvas
    var tCanvas = document.createElement('canvas');
    var tctx = tCanvas.getContext('2d');
    // let initSize = img.src.length
    var width = img.width;
    var height = img.height;
    // 如果圖片大于四百萬像素,計算壓縮比并將大小壓至400萬以下
    var ratio;
    if ((ratio = width * height / 4000000) > 1) {
      ratio = Math.sqrt(ratio);
      width /= ratio;
      height /= ratio;
    } else {
      ratio = 1;
    }
    canvas.width = width;
    canvas.height = height;
    // 鋪底色
    ctx.fillStyle = '#000';
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    // 如果圖片像素大于100萬則使用瓦片繪制
    var count;
    if ((count = width * height / 1000000) > 1) {
      count = ~~(Math.sqrt(count) + 1); // 計算要分成多少塊瓦片
      // 計算每塊瓦片的寬和高
      var nw = ~~(width / count);
      var nh = ~~(height / count);
      tCanvas.width = nw;
      tCanvas.height = nh;
      for (let i = 0; i < count; i++) {
        for (let j = 0; j < count; j++) {
          tctx.drawImage(img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh);
          ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh);
        }
      }
    } else {
      ctx.drawImage(img, 0, 0, width, height);
    }
    // 進行最小壓縮
    var ndata = canvas.toDataURL('image/jpeg', 0.1);
    // console.log('壓縮前:' + initSize)
    // console.log('壓縮后:' + ndata.length)
    // console.log('壓縮率:' + ~~(100 * (initSize - ndata.length) / initSize) + "%")
    tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0;
    return ndata;
}

/**
* 獲取formdata
*/
function getFormData () {
    var isNeedShim = ~navigator.userAgent.indexOf('Android') && ~navigator.vendor.indexOf('Google') && !~navigator.userAgent.indexOf('Chrome') && navigator.userAgent.match(/AppleWebKit\/(\d+)/).pop() <= 534;
    return isNeedShim ? new this.FormDataShim() : new FormData();
}

/**
* formdata 補丁, 給不支持formdata上傳blob的android機打補丁
* @constructor
*/
function FormDataShim () {
    var o = this;
    var parts = [];
    var boundary = Array(21).join('-') + (+new Date() * (1e16 * Math.random())).toString(36);
    var oldSend = XMLHttpRequest.prototype.send;
    this.append = function (name, value, filename) {
      parts.push('--' + boundary + '\r\nContent-Disposition: form-data; name="' + name + '"');
      if (value instanceof Blob) {
        parts.push('; filename="' + (filename || 'blob') + '"\r\nContent-Type: ' + value.type + '\r\n\r\n');
        parts.push(value);
      } else {
        parts.push('\r\n\r\n' + value);
      }
      parts.push('\r\n');
    };
    
    XMLHttpRequest.prototype.send = function (val) {
      var fr;
      var data;
      var oXHR = this;
      if (val === o) {
        parts.push('--' + boundary + '--\r\n');
        data = this.getBlob(parts);
        fr = new FileReader();
        fr.onload = function () {
          oldSend.call(oXHR, fr.result);
        }
        fr.onerror = function (err) {
          throw err;
        }
        fr.readAsArrayBuffer(data);
        this.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + boundary);
        XMLHttpRequest.prototype.send = oldSend;
      } else {
        oldSend.call(this, val);
      }
    }
}

/**
* 獲取blob對象的兼容性寫法
* @param buffer
* @param format
* @returns {*}
*/
function getBlob (buffer, format) {
    try {
      return new Blob(buffer, {type: format});
    } catch (e) {
      var bb = new (window.BlobBuilder || window.WebKitBlobBuilder || window.MSBlobBuilder)();
      buffer.forEach(function (buf) {
        bb.append(buf);
      });
      return bb.getBlob(format);
    }
}

/**
* @param {string} img 圖片的base64
* @param {int} dir exif獲取的方向信息
* @param {function} next 回調方法,返回校正方向后的base64
*/
function getImgData (img, dir, next) {
    var image = new Image();
    image.onload = function () {
      var degree = 0;
      var drawWidth;
      var drawHeight;
      var width;
      var height;
      drawWidth = this.naturalWidth;
      drawHeight = this.naturalHeight;  // 以下改變一下圖片大小
      var maxSide = Math.max(drawWidth, drawHeight);
      if (maxSide > 1024) {
        var minSide = Math.min(drawWidth, drawHeight);
        minSide = minSide / maxSide * 1024;
        maxSide = 1024;
        if (drawWidth > drawHeight) {
          drawWidth = maxSide;
          drawHeight = minSide;
        } else {
          drawWidth = minSide;
          drawHeight = maxSide;
        }
      }
      var canvas = document.createElement('canvas');
      canvas.width = width = drawWidth;
      canvas.height = height = drawHeight;
      var context = canvas.getContext('2d');  // 判斷圖片方向,重置canvas大小,確定旋轉角度,iphone默認的是home鍵在右方的橫屏拍攝方式
      switch (dir) {
        // iphone橫屏拍攝,此時home鍵在左側
        case 3:
          degree = 180
          drawWidth = -width
          drawHeight = -height
          break
        // iphone豎屏拍攝,此時home鍵在下方(正常拿手機的方向)
        case 6:
          canvas.width = height
          canvas.height = width
          degree = 90
          drawWidth = width
          drawHeight = -height
          break
        // iphone豎屏拍攝,此時home鍵在上方
        case 8:
          canvas.width = height
          canvas.height = width
          degree = 270
          drawWidth = -width
          drawHeight = height
          break
      }
      // 使用canvas旋轉校正
      context.rotate(degree * Math.PI / 180)
      context.drawImage(this, 0, 0, drawWidth, drawHeight)
      // 返回校正圖片
      next(canvas.toDataURL('image/jpeg', 0.8))
    }
    image.src = img
}

如果是微信端,建議調用微信的拍照上傳,權限更多些!

希望對您有所幫助!

2018年6月26日 10:39