圖片上傳預(yù)覽,加載進(jìn)度

最近有幾個問題一直被提及,就是圖片上傳這一塊,雖然之前也說過,今天對這部分內(nèi)容進(jìn)行一個歸納和整理.

1.自定義input file樣式

input file有自己默認(rèn)的樣式,而且這個樣式一般是不能進(jìn)行修改的,所以想自定義樣式,思路是在input標(biāo)簽外套一層父級,a標(biāo)簽和div都可以,然后把input的透明度設(shè)置成0,把想要的樣式都加到父級上,這樣就能修改了
首先是CSS部分代碼:

<style>
   a {
    display: inline-block;
    width: 200px;
    height: 100px;
    background: red;
    line-height: 100px;
    text-align: center;
    color: black;
    text-decoration: none;
    position: relative;
    font-size: 25px;
   }
   
   a:hover {
    background: green;
   }
   
   input {
    position: absolute;
    right: 0;
    top: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
   }
  </style>

然后是body對應(yīng)內(nèi)容

 <a/ href="#"> // 把/去掉就好了,要不總不顯示
   圖片上傳
   <input type="file" value="瀏覽" />
  </a>

跟file類似的還有radio,想使用自定義的點(diǎn)或者圖片,可以參照上面的寫法.


上傳按鈕效果圖

如果已經(jīng)確定了上傳文件的類型,可以直接指定接受的類型,這樣能避免因類型不正確而帶來的錯誤,使用屬性accept指定文件類型,順便把多文件上傳的代碼也放進(jìn)去

<input type="file" value="瀏覽" name="up[]" id="up" multiple="multiple" accept="image/jpeg, image/gif"/>

2.上傳預(yù)覽

這部分就需要找到對應(yīng)的上傳圖片,并且顯示在屏幕上.可以上傳之后顯示返回的網(wǎng)絡(luò)圖片,也能顯示本地的圖片,網(wǎng)絡(luò)圖片依賴后臺返回?cái)?shù)據(jù),這里只說一下怎么顯示本地的圖片,做預(yù)覽
當(dāng)圖片上傳成功之后,可以給input加一個onchange事件,這個事件會在上傳之后觸發(fā)

var up = document.getElementById("up");
up.onchange = function(){
    console.log(this.files);
}

我打印了一下this.files,它包含了上傳的所有的文件,用法跟數(shù)組類似,也是下標(biāo)取值,取出來的值包含了上傳文件所有的信息,包括尺寸,文件類型,文件名等.多文件也一樣,按上傳順序用下標(biāo)取值.files還有l(wèi)ength,能獲取長度
接下來是獲取本地圖片的路徑,然后給img標(biāo)簽賦值

var img = document.getElementById("im");
   var up = document.getElementById("up");
   up.onchange = function(){
    console.log(this.files.length);
    var blob2 = URL.createObjectURL(this.files[0]);
    img.src = blob2;
}

用了一個URL對象,根據(jù)對應(yīng)上傳文件創(chuàng)建了一個路徑,然后給圖片src賦值,就實(shí)現(xiàn)了上傳圖片預(yù)覽的功能

3.FileReader 文件讀取

FileReader提供了讀取文件的方法和讀取結(jié)果的事件類型,能幫助獲取文件內(nèi)容,也能對上傳過程進(jìn)行監(jiān)聽.它的使用有兼容問題,主要是還是IE兼容

FileReader瀏覽器兼容

FileReader的使用需要通過構(gòu)造函數(shù)創(chuàng)建一個對象,然后對這個對象進(jìn)行方法調(diào)用,它有幾個方法,能把文件異步讀到內(nèi)存里:
1.readAsText(file,encoding):以純文本形式讀取文件,將讀取到的文本保存在result屬性中,第二個參數(shù)用于指定編碼類型,可選。
2.readAsDataURL(file):讀取文件以數(shù)據(jù)URL的形式保存在result屬性中。
3.readAsBinaryString(file):讀取文件并將一個二進(jìn)制字符串保存在result屬性中。
4.readAsArrayBuffer(file):讀取文件并將一個包含文件人容的ArrayBuffer保存在result屬性中.
FileReader也有對應(yīng)的狀態(tài)監(jiān)聽
事件 描述
onabort 中斷時觸發(fā)
onerror 出錯時觸發(fā)
onload 文件讀取成功完成時觸發(fā)
onloadend 讀取完成觸發(fā),無論成功或失敗
onloadstart 讀取開始時觸發(fā)
onprogress 讀取中

接下來,就用FileReader也實(shí)現(xiàn)一遍圖片預(yù)覽

var img = document.getElementById("im");
var up = document.getElementById("up");
up.onchange = function() {
    var fr = new FileReader();
    fr.onloadend = function(ev) {
     img.src = ev.target.result;
}
  fr.readAsDataURL(this.files[0]);
}

給FileReader對象一個讀取完成的方法,使用readAsDataURL會返回一個url,這個值就保存在事件對象的result里,img通過加載這個地址,完成圖片的加載

4.本地上傳進(jìn)度

不能上傳比較大的文件,如果太小的圖片,直接就是100%了,我測試使用的是視頻.用法跟之前差不多,只不過上傳過程使用onprogress方法去監(jiān)聽過程

var img = document.getElementById("im");
var up = document.getElementById("up");
up.onchange = function() {
    var fr = new FileReader();
    fr.readAsDataURL(this.files[0]);
    var total = this.files[0].size;
    fr.onprogress = function(ev) {
     console.log(ev.loaded / total);
    }
}

ev.loaded是當(dāng)前上傳的大小,total是上傳的時候獲取的文件總大小.就能計(jì)算本地上傳的進(jìn)度,進(jìn)度條的話可以用<label>把結(jié)果顯示就可以了,這個效果可以參照QQ郵箱上傳大文件時候那個進(jìn)度條來做.

5.服務(wù)器上傳進(jìn)度

這部分需要顯示的是上傳后臺的進(jìn)度,跟之前本地的有點(diǎn)區(qū)別,這部分主要還是使用ajax進(jìn)行上傳狀態(tài)的監(jiān)控,先看JQ版

var img = document.getElementById("im");
var up = document.getElementById("up");
up.onchange = function() {
    var formD = new FormData();
    formD.append("file", this.files[0]);
    $.ajax({
     type: "POST",
     url: "up.php",
     data: formD,
     processData: false,
     //必須false才會自動加上正確的Content-Type 
     contentType: false,
     xhr: function() {
      var xhr = $.ajaxSettings.xhr();
      if(onprogress && xhr.upload) {
       xhr.upload.addEventListener("progress", onprogress, false);
       return xhr;
      }
     }
    });
   }
function onprogress(evt) {
    var loaded = evt.loaded; //已經(jīng)上傳大小情況 
    var tot = evt.total; //附件總大小 
    var per = Math.floor(100 * loaded / tot); //已經(jīng)上傳的百分比 
    console.log(loaded, tot);
}

首先是formData,它可以模擬表單,使用formData能上傳文件,在使用ajax上傳的時候,先把圖片加到formData對象里,通過對象傳輸圖片
在ajax里,使用了好幾個之前沒用過的屬性,第一個是processData,默認(rèn)值是true,當(dāng)data傳來數(shù)據(jù)的時候,如果是一個對象,會處理轉(zhuǎn)換成字符串,在這里,如果還使用true的話,會報(bào)錯,所以設(shè)置成false.還有一個xhr,這個是需要返回一個XMLHttpRequest,jq的ajax沒有progress,xhr能指定對應(yīng)的XMLHttpRequest對象,所以需要給XMLHttpRequest加上progress方法,這樣能監(jiān)聽進(jìn)度,這樣就能通過JQ完成上傳的進(jìn)度加載

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容