首頁 web前端 H5教程 H5行動端圖片壓縮上傳開發流程

H5行動端圖片壓縮上傳開發流程

Dec 07, 2016 pm 01:19 PM
h5

H5活動已十分普遍,其中一種形式是讓用戶上傳圖片參與。行動端上傳圖片,用戶一般都是上傳手機相簿中的圖片,而現在手機的拍攝品質越來越高,一般單張照片的尺寸都在3M左右。若直接上傳,十分耗流量,且體驗效果也不佳。因此需要在上傳之前,先進行本地壓縮。

接下來總結在h5活動的開發中圖片壓縮上傳的功能,並標記其中踩過的幾個坑,分享給大家:

小白區必看

對於移動端圖片上傳毫無概念的話,需要補充FileReader、Blob、FormData三個概念。

1.FileReader

定義

使用FileReader物件,web應用程式可以非同步的讀取儲存在使用者電腦上的檔案(或原始資料緩衝)內容,可以使用File物件或Blob物件來指定所要處理的檔案或資料.

方法

H5行動端圖片壓縮上傳開發流程

事件處理程序

使用

var fileReader = new FileReader();
fileReader.onload = function() {
 var url = this.result;
}
//or
fileReader.onload = function(e) {
 var url = e.target.result;
}
登入後複製

2.Blob

BLOB(binary large object),二進位儲存大物件,是一個可以進位的物件。

3.FormData

利用FormData物件,你可以使用一系列的鍵值對來模擬一個完整的表單,然後使用XMLHttpRequest發送這個」表單」.

正題

移動端圖片

1)input file上傳圖片,使用FileReader讀取用戶上傳的圖片; 
2)圖片資料傳入img對象,將img繪製到canvas上,再使用canvas.toDataURL進行壓縮; 

3)取得壓縮後的base64格式圖片數據,轉成二進制,塞入formdata,最後透過xmlHttpRequest提交formdata;

1.取得圖片資料

fileEle.onchange = function() {
  if (!this.files.length) return;
  //以下考虑的是单图情况
  var _ua = window.navigator.userAgent;
  var _simpleFile = this.files[0];
  //判断是否为图片
  if (!/\/(?:jpeg|png|gif)/i.test(_simpleFile.type)) return;
  //插件exif.js获取ios图片的方向信息
  var _orientation;
  if(_ua.indexOf('iphone') > 0) {
    EXIF.getData(_simpleFile,function(){
      _orientation=EXIF.getTag(this,'Orientation');
    });
  }
  //1.读取文件,通过FileReader,将图片文件转化为DataURL,即data:img/png;base64,开头的url,可以直接放在image.src中;
  var _reader = new FileReader(),
    _img = new Image(),
    _url;
  _reader.onload = function() {
    _url = this.result;
    _img.url = _url;
    _img.onload = function () {
      var _data = compress(_img);
      uploadPhoto(_data, _orientation);
    };
  };
  _reader.readAsDataURL(_simpleFile);
};
登入後複製

2.壓縮圖片

/**
 * 计算图片的尺寸,根据尺寸压缩
 * 1. iphone手机html5上传图片方向问题,借助exif.js
 * 2. 安卓UC浏览器不支持 new Blob(),使用BlobBuilder
 * @param {Object} _img     图片
 * @param {Number} _orientation 照片信息
 * @return {String}       压缩后base64格式的图片
 */
function compress(_img, _orientation) {
  //2.计算符合目标尺寸宽高值,若上传图片的宽高都大于目标图,对目标图等比压缩;如果有一边小于,对上传图片等比放大。
  var _goalWidth = 750,         //目标宽度
    _goalHeight = 750,         //目标高度
    _imgWidth = _img.naturalWidth,   //图片宽度
    _imgHeight = _img.naturalHeight,  //图片高度
    _tempWidth = _imgWidth,      //放大或缩小后的临时宽度
    _tempHeight = _imgHeight,     //放大或缩小后的临时宽度
    _r = 0;              //压缩比
  if(_imgWidth === _goalWidth && _imgHeight === _goalHeight) {
  } else if(_imgWidth > _goalWidth && _imgHeight > _goalHeight) {//宽高都大于目标图,需等比压缩
    _r = _imgWidth / _goalWidth;
    if(_imgHeight / _goalHeight < _r) {
      _r = _imgHeight / _goalHeight;
    }
    _tempWidth = Math.ceil(_imgWidth / _r);
    _tempHeight = Math.ceil(_imgHeight / _r);
  } else {
    if(_imgWidth < _goalWidth && _imgHeight < _goalHeight) {//宽高都小于
      _r = _goalWidth / _imgWidth;
      if(_goalHeight / _imgHeight < _r) {
        _r = _goalHeight / _imgHeight;
      }
    } else {
      if(_imgWidth < _goalWidth) {     //宽小于
        _r = _goalWidth / _imgWidth;
      } else{               //高小于
        _r = _goalHeight / _imgHeight;
      }
    }
    _tempWidth = Math.ceil(_imgWidth * _r);
    _tempHeight = Math.ceil(_imgHeight * _r);
  }
  //3.利用canvas对图片进行裁剪,等比放大或缩小后进行居中裁剪
  var _canvas = e._$get(&#39;canvas-clip&#39;);
  if(!_canvas.getContext) return;
  var _context = _canvas.getContext(&#39;2d&#39;);
  _canvas.width = _tempWidth;
  _canvas.height = _tempHeight;
  var _degree;
  //ios bug,iphone手机上可能会遇到图片方向错误问题
  switch(_orientation){
    //iphone横屏拍摄,此时home键在左侧
    case 3:
      _degree=180;
      _tempWidth=-_imgWidth;
      _tempHeight=-_imgHeight;
      break;
    //iphone竖屏拍摄,此时home键在下方(正常拿手机的方向)
    case 6:
      _canvas.width=_imgHeight;
      _canvas.height=_imgWidth; 
      _degree=90;
      _tempWidth=_imgWidth;
      _tempHeight=-_imgHeight;
      break;
    //iphone竖屏拍摄,此时home键在上方
    case 8:
      _canvas.width=_imgHeight;
      _canvas.height=_imgWidth; 
      _degree=270;
      _tempWidth=-_imgWidth;
      _tempHeight=_imgHeight;
      break;
  }
  if(window.navigator.userAgent.indexOf(&#39;iphone&#39;) > 0 && !!_degree) {
    _context.rotate(_degree*Math.PI/180);
    _context.drawImage(_img, 0, 0, _tempWidth, _tempHeight); 
  } else {
    _context.drawImage(_img, 0, 0, _tempWidth, _tempHeight);
  }
  //toDataURL方法,可以获取格式为"data:image/png;base64,***"的base64图片信息;
  var _data = _canvas.toDataURL(&#39;image/jpeg&#39;);
  return _data;
}
登入後複製

3.上傳圖片

/**
 * 上传图片到NOS
 * @param {Object} _blog Blob格式的图片
 * @return {Void}
 */
function uploadPhoto(_data) {
  //4.获取canvas中的图片信息
  //window.atob方法将其中的base64格式的图片转换成二进制字符串;若将转换后的值直接赋值给Blob会报错,需Uint8Array转换:最后创建Blob对象;
  _data = _data.split(&#39;,&#39;)[1];
  _data = window.atob(_data);
  //如果不用ArrayBuffer,发送给服务器的图片格式是[object Uint8Array],上传失败...
  var _buffer = new ArrayBuffer(_data.length);
  var _ubuffer = new Uint8Array(_buffer);
  for (var i = 0; i < _data.length; i++) {
    _ubuffer[i] = _data.charCodeAt(i);
  }
  // 安卓 UC浏览器不支持 new Blob(),使用BlobBuilder
  var _blob;
  try {
    _blob = new Blob([_buffer], {type:&#39;image/jpeg&#39;});
  } catch(ee) {
    window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;
    if (ee.name == &#39;TypeError&#39; && window.BlobBuilder) {
      var _bb = new BlobBuilder();
      _bb.append(_buffer);
      _blob = _bb.getBlob(&#39;image/jpeg&#39;);
    }
  }
  var _suffix = &#39;jpg&#39;;
  if(_blob.type === &#39;image/jpeg&#39;) {
    _suffix = &#39;jpg&#39;;
  }
  //获取NOStoken
  this.__cache._$requestDWRByGet({url: &#39;ImageBean.genTokens&#39;,param: [_suffix,&#39;&#39;,&#39;&#39;,&#39;&#39;,&#39;1&#39;],onload: function(_tokens) {
    _tokens = _tokens || [];
    var _token = _tokens[0];
    if(!_token || !_token.objectName || !_token.uploadToken){
      alert(&#39;token获取失败!&#39;);
      return false;
    }
    //上传图片到NOS
    var _objectName = _token.objectName,
      _uploadToken = _token.uploadToken,
      _bucketName = _token.bucketName;
    var _formData = new FormData();
    _formData.append(&#39;Object&#39;, _objectName);
    _formData.append(&#39;x-nos-token&#39;, _uploadToken);
    _formData.append(&#39;file&#39;,_blob);
    var _xhr;
    if (window.XMLHttpRequest) {
      _xhr = new window.XMLHttpRequest();
    } else if (window.ActiveXObject) {
      _xhr = new ActiveXObject("Microsoft.XMLHTTP");
    }
    _xhr.onreadystatechange = function() {
      if(_xhr.readyState === 4) {
        if((_xhr.status >= 200 && _xhr.status < 300) || _xhr.status === 304) {
          var _imgurl = "http://nos.netease.com/" + _bucketName + "/" + _objectName + "?imageView";
          var _newUrl = mb.x._$imgResize(_imgurl, 750, 750, 1, true);
          window.location.href = &#39;http://www.lofter.com/act/taxiu?op=effect&originImgUrl=&#39; + _newUrl;
        }
      }
    };
    _xhr.open(&#39;POST&#39;, &#39;http://nos.netease.com/&#39; + _bucketName, true);
    _xhr.send(_formData);
  }});
}
登入後複製
exif

至此H5圖片壓縮上傳的流程結束。


🎜
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1665
14
CakePHP 教程
1424
52
Laravel 教程
1322
25
PHP教程
1269
29
C# 教程
1249
24
h5是指什麼 h5是指什麼 Aug 02, 2023 pm 01:52 PM

H5是指HTML5,是HTML的最新版本,H5是一個功能強大的標記語言,為開發者提供了更多的選擇和創造空間,它的出現推動了Web技術的發展,使得網頁的交互和效果更加出色,隨著H5技術的逐漸成熟和普及,相信它將在互聯網的世界中發揮越來越重要的作用。

如何區分H5,WEB前端,大前端,WEB全端? 如何區分H5,WEB前端,大前端,WEB全端? Aug 03, 2022 pm 04:00 PM

本文帶你快速區分H5、WEB前端、大前端、WEB全棧,希望對需要的朋友有幫助!

h5怎麼實現web端向上滑動載入下一頁 h5怎麼實現web端向上滑動載入下一頁 Mar 11, 2024 am 10:26 AM

實現步驟:1、監聽頁面的滾動事件;2、判斷捲動至頁面底部;3、載入下一頁資料;4、更新頁面捲動位置即可。

h5如何使用position h5如何使用position Dec 26, 2023 pm 01:39 PM

在H5中使用position屬性可以透過CSS控制元素的定位方式:1、相對定位relative,語法為「style="position: relative;」;2、絕對定位absolute,語法為「style="position: absolute; 」;3、固定定位fixed,語法為「style="position: fixed;」等等。

H5代碼:可訪問性和語義HTML H5代碼:可訪問性和語義HTML Apr 09, 2025 am 12:05 AM

H5通過語義化元素和ARIA屬性提升網頁的可訪問性和SEO效果。 1.使用、、等元素組織內容結構,提高SEO。 2.ARIA屬性如aria-label增強可訪問性,輔助技術用戶可順利使用網頁。

H5指的是什麼?探索上下文 H5指的是什麼?探索上下文 Apr 12, 2025 am 12:03 AM

H5referstoHTML5,apivotaltechnologyinwebdevelopment.1)HTML5introducesnewelementsandAPIsforrich,dynamicwebapplications.2)Itsupportsmultimediawithoutplugins,enhancinguserexperienceacrossdevices.3)SemanticelementsimprovecontentstructureandSEO.4)H5'srespo

vue3怎麼實作H5表單驗證元件 vue3怎麼實作H5表單驗證元件 Jun 03, 2023 pm 02:09 PM

效果圖描述基於vue.js,不依賴其他外掛程式或函式庫實作;基礎功能使用保持和element-ui一致,內部實作做了一些行動裝置差異的調整。目前建置平台使用uni-app官方腳手架構建,因為當下行動端大多情況就h6和微信小程式兩種,所以一套程式碼跑多端十分適合技術選型。實作思路核心api:使用provide和inject,對應和。在元件中,內部用一個變數(陣列)去將所有實例儲存起來,同時把要傳遞的資料透過provide暴露出去;元件則在內部用inject去接收父元件提供過來的數據,最後把自身的屬性和方法提交

H5與HTML5相同嗎? H5與HTML5相同嗎? Apr 08, 2025 am 12:16 AM

"h5"和"HTML5"在大多數情況下是相同的,但它們在某些特定場景下可能有不同的含義。 1."HTML5"是W3C定義的標準,包含新標籤和API。 2."h5"通常是HTML5的簡稱,但在移動開發中可能指基於HTML5的框架。理解這些區別有助於在項目中準確使用這些術語。

See all articles