圖片上傳及圖片處理

胡九筒發表於2019-03-22

一.input type=file與檔案上傳

<input type="file">
複製程式碼

如果想使用瀏覽器原生特性實現檔案上傳(如圖片)效果,父級的form元素有個東西不能丟

enctype="multipart/form-data"
複製程式碼

enctype屬性規定在傳送到伺服器之前應該如何對錶單資料進行編碼,預設的編碼是:”application/x-www-form-urlencoded“。對於普通資料是挺適用的,但是,對於檔案,科科,就不能亂編碼了,該什麼就是什麼,只能使用multipart/form-data作為enctype屬性值。

只上傳資料夾而不是檔案
<input type="file" webkitdirectory directory multiple/> 
複製程式碼
UI自定義
<label class="ui_button ui_button_primary" for="xFile">上傳檔案</label> <form><input type="file" id="xFile" style="position:absolute;clip:rect(0 0 0 0);"></form> 
複製程式碼
accept屬性(用來指定瀏覽器接受的檔案型別)
<input type="file" accept="image/*" > //只允許傳圖片 <input type="file" accept="image/png,image/jpeg,image/gif,image/jpg"> //只允許傳圖片
``` accept屬性是MIME型別: 
複製程式碼

accept="application/pdf" accept="audio/x-mpeg" accept="text/html" .accept="video/x-mpeg2" ``` 多個屬性值使用逗號分隔:

<input accept="audio/*,video/*,image/*"> 
複製程式碼

二.圖片上傳/壓縮/水印/方向問題

1.FileReader.readAsDataURL():該方法會讀取指定的 Blob 或 File 物件。讀取操作完成的時候,readyState 會變成已完成(DONE),並觸發 loadend 事件,同時 result 屬性將包含一個data:URL格式的字串(base64編碼)以表示所讀取檔案的內容。
2.HTMLCanvasElement.toDataURL()返回一個包含圖片展示的 data URI 。可以使用 type 引數其型別,預設為 PNG 格式。圖片的解析度為96dpi
//語法:
canvas.toDataURL(type, encoderOptions); 
//type(可選):圖片格式,預設為 image/png; 
//encoderOptions(可選) :在指定圖片格式為 image/jpeg 或 image/webp的情況下,可以從 0 到 1 的區間內選擇圖片的質量。如果超出取值範圍,將會使用預設值 0.92。
//返回值:包含 data URI 的DOMString。 
複製程式碼

2.1圖片上傳

//html 
<label class="ui_button ui_button_primary" for="xFile">上傳檔案</label>
<form>
    <input type="file" id="uploadFile" style="position:absolute;clip:rect(0 0 0 0);">
</form> 
<img id="imgCover" src="./watermark.png" class="clip"> //水印小照片
<p id="compounded"></p> //合成後的照片 
//js 
var eleUploadFile = document.getElementById('uploadFile'); 
var compounded = document.getElementById('compounded');
eleUploadFile.addEventListener('change', function (event) { 
    var file = event.target.files[0]; //獲取圖片資源 
    if (!event.type.match('image.*')) {// 只選擇圖片檔案 
        return false; 
    } 
    var reader = new FileReader(); 
    reader.readAsDataURL(file); // 讀取檔案 exif(file); //旋轉圖片 reader.onloadend=function(e){ //檔案讀取結束 
        var base64 = e.target.result; 
        if (base64.length > 1024 * 50) { 
            console.error('圖片尺寸請小於50K'); 
            return; 
        } 
        var compressImg = compress(base64); //壓縮函式 
        var compoundImg = compoundImg(base64,function(url){ 
            var size = 180 / (window.devicePixelRatio || 1); 
            compounded.innerHTML = '<img src="'+ url +'" width="'+ size +'" height="'+ size +'">'; 
        }) 
    } 
})
複製程式碼

2.2圖片壓縮

function compress(readerResult) { //readerResult-->傳入檔案base64結果 
    var img = new Image(); 
    img.src = readerResult; 
    if(readerResult.length<80000) { 
        return readerResult ;//小於80K的不壓縮 
    } 
    //用於壓縮圖片的canvas 
    let canvas = document.createElement("canvas"); 
    let ctx = canvas.getContext("2d"); 

    //畫圖區域 
    canvas.width = img.naturalWidth; 
    canvas.height = img.naturalHeight; 
    //鋪底色 
    ctx.fillStyle = "#fff"; 
    ctx.fillRect(0, 0, canvas.width, canvas.height); 
    ctx.drawImage(img, 0, 0, img.naturalWidth, img.naturalHeight); 
    //進行最小壓縮 
    var dataURL = canvas.toDataURL("image/jpeg",0.9); 
    return dataURL; 
}
複製程式碼

2.3圖片水印

function compoundImg(url,callback) { //url -->合成水印較大的那張圖的base64碼 
    var eleImgCover = document.getElementById('imgCover'); 
    var canvas = document.createElement('canvas'); 
    var size = 180; //水印大小 
    canvas.width = size; 
    canvas.height = size; 
    var context = canvas.getContext('2d'); // 這是上傳影象 
    var imgUpload = new Image(); 
    imgUpload.onload = function () { // 繪製 
        context.drawImage(imgUpload, 0, 0, size, size, 0,0, size, size); // 再次繪製(繪製上水印小照片) 
        context.drawImage(eleImgCover, 0, 0, size, size, 0,0, size, size); // 回撥 callback(canvas.toDataURL('image/png'));
    }; 
    imgUpload.src = url; 
} 
複製程式碼

2.4 EXIF.JS 處理圖片方向資訊

<script src="EXIF.js"></script> //先引入EXIF.js 
function exif(file) { 
    var Orientation = ''; 
    EXIF.getData(file, function() { 
        console.log(EXIF.pretty(this)); 
        EXIF.getAllTags(this); 
        console.log(EXIF.getTag(this, 'Orientation'));
        Orientation = EXIF.getTag(this, 'Orientation'); //return; }); 
        if (navigator.userAgent.match(/iphone/i)) { //如果方向角不為1,都需要進行旋轉
            if(Orientation != "" && Orientation != 1){ 
                switch(Orientation){ 
                    case 6://需要順時針(向左)90度旋轉
                        console.log('需要順時針(向左)90度旋轉');
                        break; 
                    case 8://需要逆時針(向右)90度旋轉
                        console.log('需要順時針(向右)90度旋轉'); 
                        break; 
                    case 3://需要180度旋轉 alert('需要180度旋轉');
                        console.log('需要180度旋轉'); 
                        break; 
                } 
            } 
    } 
} 
複製程式碼

2.5 html2canvas合成圖片

function html2canvas(node) { // node為要合成圖片的dom節點
    const weNeedImageUrl = ''
    const scale = window.devicePixelRatio
    // 防止在高倍屏下合成圖片過於模糊
    const createCanvas = document.createElement('canvas')
    createCanvas.width = node.offsetWidth * scale
    createCanvas.height = node.offsetHeight * scale
    const ctx = createCanvas.getContext('2d')
    ctx.scale(scale, scale)
    html2canvas(node, {
        scale: scale,
        dpi: 384,
        canvas: createCanvas,
        width: node.offsetWidth,
        height: node.offsetHeight
      }).then((canvas) => {
        // 合成圖片後的base64碼
        let domToImgUrl = canvas.toDataURL('image/jpeg', 0.92)
        console.log('合成圖片大小:', domToImgUrl.length)
        
        // 下面是將圖片的base64以blob形式上傳到阿里雲檔案伺服器,獲取圖片地址
        let domImageArr = domToImgUrl.split(',')
        let mime = domImageArr[0].match(/:(.*?);/)[1]                 // 獲取影象型別
        let decodeData = atob(domImageArr[1])                         // 解碼base64
        let decodeDataLength = decodeData.length
        let uInt8array = new Uint8Array(decodeDataLength)
        //Uint8Array型別陣列表示的8位無符號整數陣列。內容被初始化為0
        while (decodeDataLength--) {
            uInt8array[decodeDataLength] = decodeData.charCodeAt(decodeDataLength)
        }
        let blob = new Blob([uInt8array], { type: mime })
        let formData = new FormData()
        formData.append('file', blob, 'image.png')
        // 上傳該圖片到阿里雲
        appUploadFile(formData).then(data => {
            weNeedImageUrl = data.data[0]
            return weNeedImageUrl
        })
    })
    
}
複製程式碼

相關文章