1. 程式人生 > >前端預覽input上傳的圖片

前端預覽input上傳的圖片

既然要實現在前端預覽上傳的圖片,我們需要先了解input 和 file型別

Input 標籤的file型別,提供了上傳檔案的功能,通過此型別,可以上傳檔案到伺服器。

input的file型別,在上傳檔案時,會返回一個File物件,這個物件會存在一個FileList數組裡邊。之所以存在數組裡邊,主要是方便實現多檔案上傳。File物件繼承自Blob物件,也就是說Blob物件的屬性和方法,File物件也可以使用,而File物件本身也有自己的屬性和方法。

下圖是瀏覽器打印出來的FileList : 

各項代表的意思分別是:

  • lastModified屬性,返回File物件引用檔案最後的修改時間。
  • lastModifiedDate屬性,引用檔案最後修改時間的Date物件。
  • name屬性,所引用檔案的名字。
  • size屬性,返回檔案大小。
  • webkitRelativePath屬性,相關的Path或URL。
  • type屬性,返回檔案的多用途網際網路郵件擴充套件型別(MIME型別)。
  • getAsBinary() 將檔案內容按照原始二進位制形式解析成字串並返回.

前端顯示上傳圖片有兩種方法:

上傳照片前                                                                上傳照片後

 HTML: 

<div id="containner">       
        <input type="file"  id="imgFile" onchange="previewFile()"><br>
        <img src="" height="200" alt="Image preview...">           
</div>

 JS:

1、通過window.URL.createObjectURL(blob) 

      blob 為Blob物件 或者 File物件

    這個方法會根據傳入的引數建立一個指向該引數物件的URL. 這個URL的生命僅存在於它被建立的這個文件裡

 function previewFile() {
            var preview = document.querySelector('img')          
            var fileDom = document.querySelector('input[type=file]')
            // 獲取得到file 物件
            var file = fileDom.files[0]
            // 限制上傳圖片的大小
            if(file.size > 1024 * 1024 * 2) {
	            alert('圖片大小不能超過 2MB!');
	            return false;
            }
            // 建立url
            var imgUrl = window.URL.createObjectURL(file)
            preview.setAttribute("src", imgUrl)
            // 更改img url 以後釋放 url
            preview.onload = function() {
                // console.log('圖片載入成功')
                URL.revokeObjectURL(imgUrl)
            }
  }

附註:

在每次呼叫 createObjectURL() 方法時,都會建立一個新的 URL 物件,即使你已經用相同的物件作為引數建立過。

所以當不再需要這些 URL 物件時,每個物件必須通過呼叫 URL.revokeObjectURL() 方法來釋放。瀏覽器會在文件退出的時候自動釋放它們,但是為了獲得最佳效能和記憶體使用狀況,你應該在安全的時機主動釋放掉它們。

2、通過FileReader.readAsDataURL(blob)

  blob 為Blob物件 或者 File物件

     讀取操作完成的時候,readyState 會變成已完成(DONE),並觸發 loadend 事件,同時 result 屬性將包含一個data:URL格式的字串(base64編碼)以表示所讀取檔案的內容,如圖(為擷取的一部分):

 function previewFile() {
     var preview = document.querySelector('img');
     var fileDom = document.querySelector('input[type=file]')
     var file = fileDom.files[0]
     // 限制上傳圖片的大小
     if(file.size > 1024 * 1024 * 2) {
	      alert('圖片大小不能超過 2MB!');
	      return false;
     }
     // 當前瀏覽器支援FileReader
     if(window.FileReader) {
         var reader  = new FileReader()
         reader.readAsDataURL(file)
         reader.addEventListener("load", function () {
             console.log('reader.result', reader.result)
             preview.src = reader.result
         }, false)
     }else {
         alert('Not supported by your browser!')
     } 
  }

FileReader 

     FileReader 物件允許Web應用程式非同步讀取儲存在使用者計算機上的檔案(或原始資料緩衝區)的內容,使用 File 或 Blob 物件來指定要讀取的檔案或資料,即 FileReader.readAsDataURL(blob)  的 引數blob 為 File物件 或 Blob 物件。 同時也適用於window.URL.createObjectURL()

  File物件: 

  •           可以是來自使用者在一個<input>元素上選擇檔案後返回的FileList物件         
  •           可以是來自拖放操作生成的 DataTransfer物件
  •           可以是來自在一個HTMLCanvasElement上執行mozGetAsFile()方法後返回結果

 blob物件(二進位制資料):

  •           通過new Blob()建立的物件就是Blob物件(關於Blob物件 ,下一篇再寫)
  •           XMLHttpRequest裡,如果指定responseType為blob,那麼得到的返回值也是一個blob物件.

 上面這兩種方式,都可以讓圖片在前端頁面顯示,但是如果需要將圖片的資料傳送給伺服器,FileReader.readAsDataURL 這種方式更好,可以將得到的資料作為data傳遞給伺服器。

3、如果拿到圖片的地址,可以通過獲取圖片的blob物件,然後再通過FileReader.readAsDataURL(blob)拿到圖片data

    第一步 :傳送ajax請求去獲取url 的blob值

 function getImageBlob(url){
            const xhr = new XMLHttpRequest()
            xhr.open("get", url, true)
            // 設定responseType 的型別, 為arraybuffer、blob都可以
            xhr.responseType = "blob"
            return new Promise((resolve, reject) => {
                xhr.onload = () => {
                     resolve(xhr.response)
                }
                xhr.onerror = () => reject()
                xhr.send()
            })
        }

第二步: 獲取圖片資料

function getImageData(imgBlob) {
            // imgBlob 是一個ArrayBuffer型別的物件或者Blob物件
            return new Promise((resolve, reject) => {
                const reader = new FileReader()
                reader.onloadend = () => resolve(reader.result)
                reader.onerror = reject
                // 設定轉換的URL的型別,通過Blob 建構函式的type 來設定讀取出來的資料的型別
                reader.readAsDataURL(new Blob([img], { type: "image/jpeg" }))
            });
        }

第三步: 封裝

function urlToData(url) {
            return getImageData(url).then((imageData) =>
                getTypeOfImage(imageData)
            )
        }

最後通過 await urlToData(url) 就可以得到圖片的資料了