js前端上傳文件縮略圖技巧示例詳解
引言
通常情況下,前端提交給服務(wù)器的數(shù)據(jù)格式為JSON格式,但很多時(shí)候用戶想上傳自己的頭像、視頻等,這些非文本數(shù)據(jù)的時(shí)候,就不能直接以JSON格式上傳到后端了。
當(dāng)我們要獲取用戶上傳的文件,可以使用input表單項(xiàng),將type屬性值設(shè)置為“file”。
<form action=""> <input type="file" name="file"> </form>
同時(shí),我們?yōu)楸韱雾?xiàng)綁定change事件,當(dāng)用戶上傳文件時(shí),我們就可以在事件對(duì)象中獲取到用戶上傳的文件。
<script> const inp = document.querySelector("input") inp.onchange = function(e) { console.log(e.target.files); } </script>
但需要注意的是 e.target.files
是一個(gè)類數(shù)組(FileList),會(huì)將你上傳的多個(gè)文件都存儲(chǔ)在這個(gè)數(shù)組中,而這個(gè)例子中我們只上傳一個(gè)文件,所以我們用 e.target.files[0]
將這個(gè)文件對(duì)象取出來。(若想上傳多個(gè)文件,可以在input標(biāo)簽中增加multiple屬性)。
文件對(duì)象簡介
在學(xué)習(xí)上傳文件前,我們先簡單了解四個(gè)與文件相關(guān)的內(nèi)置對(duì)象。
Blob
Blob是一個(gè)存儲(chǔ)二進(jìn)制的對(duì)象,實(shí)際上很少直接使用這個(gè)對(duì)象。
- size 屬性,返回Blob對(duì)象的字節(jié)數(shù),即文件的大小。
const input = document.getElementById('input'); const output = document.getElementById('output'); input.addEventListener('change', (e) => { output.innerText = `文件的大小為${e.target.files[0].size}`; });
- slice() 方法,對(duì)Blob對(duì)象進(jìn)行切片,返回新的Blob對(duì)象。
- 可以用這個(gè)方法實(shí)現(xiàn)大文件切片上傳。
var blob = new Blob().slice([start [, end [, contentType]]]}; /* - start 開始位置的下標(biāo) - end 結(jié)束位置的下標(biāo) - contentType 給新的Blob賦予一個(gè)新的文檔類型。這將會(huì)把它的 type 屬性設(shè)為被傳入的值。它的默認(rèn)值是一個(gè)空的字符串 */
File
- 通常情況下, File 對(duì)象是來自用戶在一個(gè)
<input>
元素上選擇文件后返回的 FileList 對(duì)象,也可以是來自由拖放操作生成的 DataTransfer 對(duì)象。 - file 對(duì)象是Blob的一個(gè)子類,因此file對(duì)象可以直接使用Blob中的方法和屬性。
const input = document.getElementById('input'); input.addEventListener('change', (e) => { let file = e.target.files[0] if(file.size > 4 * 1024 * 1024 || file.type != "image/jpeg"){ alert("文件不得大于4M,且圖片格式要為jpg格式。") } });
FileReader
- 異步讀取存儲(chǔ)在用戶計(jì)算機(jī)上的文件(或原始數(shù)據(jù)緩沖區(qū))的內(nèi)容,使用 File 或 Blob 對(duì)象指定要讀取的文件或數(shù)據(jù)。
var fr = new FileReader();
- readAsDataURL(),讀取指定的 Blob 或 File 對(duì)象。讀取操作完成的時(shí)候,readyState 會(huì)變成已完成DONE,并觸發(fā) loadend 事件,同時(shí) result 屬性將包含一個(gè)data:URL 格式的字符串(base64 編碼)以表示所讀取文件的內(nèi)容。
fr.readAsDataURL(blob) /* - blob,被讀取的 blob 或 file對(duì)象 */
- readAsText(),將 Blob 或者 File 對(duì)象根據(jù)特殊的編碼格式轉(zhuǎn)化為內(nèi)容 (字符串形式)。
fr.readAsDataURL(blob) /* - blob,被讀取的 blob 或 file對(duì)象 */
注意,以上兩個(gè)方法都是異步的,也就是說,只有當(dāng)執(zhí)行完成后才能夠查看到結(jié)果,如果直接查看是無結(jié)果的,并返回 undefined。我們需要為fr掛載load或loadend事件,在事件回調(diào)中使用result
屬性才能獲取結(jié)果。
<input type="file" onchange="previewFile()"> <img src="" height="200"> <script> function previewFile(e) { var img = document.querySelector('img'); let file = e.target.files[0]; let fr = new FileReader(); reader.readAsDataURL(file); fr.addEventListener("load", function () { img.src = fr.result; }); } </script>
FormData
- 提供了一種表示表單數(shù)據(jù)的鍵值對(duì) key/value 的構(gòu)造方式。
- 在
<form>
標(biāo)簽中,我們直接點(diǎn)擊提交按鈕,瀏覽器會(huì)以默認(rèn)以x-www-form-urlencoded的數(shù)據(jù)格式向服務(wù)器提交數(shù)據(jù)。 - 當(dāng)我們?yōu)?code>form標(biāo)簽設(shè)置enctype屬性時(shí),可以設(shè)置發(fā)送的數(shù)據(jù)格式。
<!-- application/x-www-form-urlencoded 在發(fā)送前編碼所有字符(默認(rèn)) multipart/form-data 不對(duì)字符編碼。在使用包含文件上傳控件的表單時(shí),必須使用該值 text/plain 空格轉(zhuǎn)換為 "+" 加號(hào),但不對(duì)特殊字符編碼。 --> <form action="/upload" enctype="multipart/form-data" method="post"> <input type="text" name="username"> <input type="password" name="password"> <input type="file" name="file"> <input type="submit"> </form>
在上面的例子中,瀏覽器會(huì)以formdata的數(shù)據(jù)格式向服務(wù)器發(fā)送表單數(shù)據(jù),但我們使用框架來編寫業(yè)務(wù)時(shí),我們不會(huì)直接使用表單提交數(shù)據(jù),通常都是將表單中的數(shù)據(jù)提取出來,手動(dòng)構(gòu)建出相應(yīng)的數(shù)據(jù)格式,再用aixos發(fā)送給服務(wù)器,所以我們需要主動(dòng)使用FormData對(duì)象封裝file對(duì)象
- append() 方法,向 FormData 中添加新的屬性值,F(xiàn)ormData 對(duì)應(yīng)的屬性值存在也不會(huì)覆蓋原值,而是新增一個(gè)值,如果屬性不存在則新增一項(xiàng)屬性值。
function previewFile(e) { const formdata = new FormData() formData.append("userAvatar", e.target.files[0]); } /* 第一個(gè)值為文件名稱,第二個(gè)值為要傳送的文件對(duì)象/字符串 */
文件對(duì)象之間的關(guān)系
- 由上圖可以看出,當(dāng)我們通過input標(biāo)簽上傳文件時(shí),我們可以得到一個(gè)file對(duì)象,file對(duì)象與blob對(duì)象可以互相轉(zhuǎn)換,但要將文件對(duì)象上傳給服務(wù)器則是不允許的,因?yàn)楹蠖藷o法識(shí)別這種對(duì)象,因此我們需要將文件對(duì)象包裝成formdata對(duì)象,或者轉(zhuǎn)換為base64等文本格式再傳給后端。
function previewFile(e) { let file = e.target.files[0]; let formdata = new FormData() formdata.append("userAva", file) // 注意,若要實(shí)現(xiàn)大文件分片上傳時(shí),同一個(gè)文件分片的文件名要相同,方便后端拼接 axios.post("http://localhost/...", { data: formdata }).then( res => { console.log(res) ) }
縮略圖的實(shí)現(xiàn)
我們通過input標(biāo)簽上傳圖片后,用戶無法查看所提交的圖片。
因此為了提高用戶體驗(yàn),我們?cè)谟脩籼峤粓D片后,將圖片在頁面中顯示出來。
<form action=""> <input type="file" name="file"><br/> <img src="" alt=""> </form> <script> const inp = document.querySelector("input") const img = document.querySelector("img") const fr = new FileReader() inp.onchange = function(e) { let file = e.target.files[0] fr.readAsDataURL(file) } fr.onload = function() { img.src = fr.result } </script>
未提交前
提交后
總結(jié)
- 前端上傳文件時(shí)需要使用FormData對(duì)象對(duì)文件進(jìn)行包裝后才能傳給服務(wù)器。
- 獲取用戶上傳的圖片后,使用FileReader對(duì)象中提供的readAsDataUrl()方法,將圖片轉(zhuǎn)化為base64格式,再將base64編碼讓img標(biāo)簽加載,實(shí)現(xiàn)縮略圖的效果。
以上就是js前端上傳文件縮略圖技巧示例詳解的詳細(xì)內(nèi)容,更多關(guān)于js前端上傳文件縮略圖的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
一個(gè)JavaScript獲取元素當(dāng)前高度的實(shí)例
這篇文章主要為大家介紹了一個(gè)JavaScript獲取元素當(dāng)前高度的實(shí)例,比較實(shí)用,建議新手朋友們可以看看2014-10-10JavaScript實(shí)現(xiàn)擦玻璃效果分析鼠標(biāo)移動(dòng)響應(yīng)時(shí)間粒度問題
這篇文章主要為大家介紹了JavaScript實(shí)現(xiàn)擦玻璃效果分析鼠標(biāo)移動(dòng)響應(yīng)時(shí)間粒度問題詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10深入理解javascript學(xué)習(xí)筆記(一) 編寫高質(zhì)量代碼
編寫高質(zhì)量JavaScript的一些要素,例如避免全局變量,使用單變量聲明,在循環(huán)中預(yù)緩存length(長度),遵循代碼閱讀,以及更多2012-08-08js貪吃蛇網(wǎng)頁版游戲特效代碼分享(挑戰(zhàn)十關(guān))
這篇文章主要為大家詳細(xì)介紹了js貪吃蛇網(wǎng)頁版游戲特效,游戲總共有十關(guān),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2015-08-08JavaScript不使用prototype和new實(shí)現(xiàn)繼承機(jī)制
這篇文章主要介紹了JavaScript不使用prototype和new實(shí)現(xiàn)繼承機(jī)制的相關(guān)資料,需要的朋友可以參考下2014-12-12用js實(shí)現(xiàn)計(jì)算加載頁面所用的時(shí)間
用js實(shí)現(xiàn)計(jì)算加載頁面所用的時(shí)間的代碼,需要的朋友可以參考下。2010-04-04