HTML5 本地裁剪圖片並上傳至服務器(老梗)

不少狀況下用戶上傳的圖片都須要通過裁剪,好比頭像啊什麼的。但之前實現這類需求都很複雜,每每須要先把圖片上傳到服務器,而後返回給用戶,讓用戶肯定裁剪座標,發送給服務器,服務器裁剪完再返回給用戶,來回須要 5 步。步驟繁瑣不說,當不少用戶上傳圖片的時候也很影響服務器性能。javascript

HTML5 的出現讓咱們能夠更方便的實現這一需求。雖然這裏所說的技術都貌似有點過期了(前端界的「過期」,你懂的),但仍是有些許參考價值。在這裏我只說一下要點,具體實現同窗們慢慢研究。html

下面奉上我本身寫的一個demo,在輸入框中選好本身服務器 url, 生成好圖片後點擊 Submit 上傳,而後本身去服務器裏看看效果吧~~前端

瀏覽器要求支持如下 Feature:java

代碼直接從現有項目移植過來,沒有通過「太多的」測試,寫的很亂,也沒註釋,你們就慢慢看吧。。。重點就在 js 腳本的 28 行,clipImage 函數中,同窗們能夠直接跳過去看。jquery

http://jsfiddle.net/windwhinny/d5qan0q7/ajax

第一步:獲取文件

HTML5 支持從 input[type=file] 元素中直接獲取文件信息,也能夠讀取文件內容。咱們用下面代碼就能夠實現:canvas

javascript$('input[type=file]').change(function(){
    var file=this.files[0];
    // continue ...
});

第二部:讀取文件,並生成 Image 元素

這一步就須要用到 FileReader 了,這個類是專門用來讀取本地文件的。純文本或者二進制均可以讀取,可是本地文件必須是通過用戶容許才能讀取,也就是說用戶要在input[type=file]中選擇了這個文件,你才能讀取到它。瀏覽器

經過 FileReader 咱們能夠將圖片文件轉化成 DataURL,就是以 data:image/png;base64, 開頭的一種URL,而後能夠直接放在 image.src 裏,這樣本地圖片就顯示出來了。服務器

javascript$('input[type=file]').change(function(){
    var file=this.files[0];

    var reader=new FileReader();
    reader.onload=function(){
        // 經過 reader.result 來訪問生成的 DataURL
        var url=reader.result;
        setImageURL(url);
    };
    reader.readAsDataURL(file);
});

var image=new Image();
function setImageURL(url){
    image.src=url;
}

Image 就是在 html 裏的 <img> 標籤,因此能夠直接插入到文檔流裏。app

第三步:獲取裁剪座標

這一步沒啥好說的,實現的方法也不少,須要得到下面四個裁剪框的座標:

  • Y座標
  • X座標
  • 高度
  • 寬度

以下圖所示:
圖片描述

第四部:裁剪圖片

這是時候咱們就須要用到 canvas 了,canvas 和圖片同樣,因此新建 canvas 時就要肯定其高寬。這裏咱們還運用到 image.naturalHeightimage.naturalWidth 這兩個屬性來獲取圖片原始尺寸。

將圖片放置入 canvas 時須要調用 drawImage ,這個接口參數比較多,在 MDN 上有詳細的說明。

javascriptdrawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)

=Canvas_drawimage.jpg

由於咱們用 canvas 只是用於裁剪圖片的,因此須要新建一個 canvas 讓它的尺寸和裁剪以後圖片的尺寸相等,此時 canvas 就至關與咱們的裁剪框。運用這個函數還能夠將大圖縮放成小圖,同窗們本身研究吧。

javascript// 如下四個參數由第三步得到
var x,  
    y,
    width,
    height;

var canvas=$('<canvas width="'+width+'" height="'+height+'"></canvas>')[0],
    ctx=canvas.getContext('2d');

ctx.drawImage(image,x,y,width,height,0,0,width,height);
$(document.body).append(canvas);

canvas 加入文檔流以後,就能夠看到裁剪後的效果了。不過咱們還須要將圖片上傳至服務器裏。

第五步:讀取裁剪後的圖片並上傳

這時咱們要獲取 canvas 中圖片的信息,用 toDataURL 就能夠轉換成上面用到的 DataURL 。 而後取出其中 base64 信息,再用 window.atob 轉換成由二進制字符串。但 window.atob 轉換後的結果仍然是字符串,直接給 Blob 仍是會出錯。因此又要用 Uint8Array 轉換一下。總之這裏挺麻煩的。。

javascriptvar data=canvas.toDataURL();

// dataURL 的格式爲 「data:image/png;base64,****」,逗號以前都是一些說明性的文字,咱們只須要逗號以後的就好了
data=data.split(',')[1];
data=window.atob(data);
var ia = new Uint8Array(data.length);
for (var i = 0; i < data.length; i++) {
    ia[i] = data.charCodeAt(i);
};

// canvas.toDataURL 返回的默認格式就是 image/png
var blob=new Blob([ia], {type:"image/png"});

這時候裁剪後的文件就儲存在 blob 裏了,咱們能夠把它看成是普通文件同樣,加入到 FormData 裏,並上傳至服務器了。

FormData 顧名思義,就是用來建立表單數據的,用 append 以鍵值的形式將數據加入進去便可。但他最大的特色就是能夠手工添加文件或者 Blob 類型的數據,Blob 數據也會被看成文件來處理。原生 js 能夠直接傳遞給 xhr.send(fd), jquery 能夠放入 data 裏請求。

javascriptvar fd=new FormData();

fd.append('file',blob);
$.ajax({
    url:"your.server.com",
    type:"POST",
    data:fd,
    success:function(){}
});

而後你服務器裏應該就能夠收到這個文件了~

相關文章
相關標籤/搜索