溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

js怎么實(shí)現(xiàn)圖片上傳預(yù)覽原理

發(fā)布時(shí)間:2021-04-23 11:12:50 來源:億速云 閱讀:189 作者:小新 欄目:web開發(fā)

小編給大家分享一下js怎么實(shí)現(xiàn)圖片上傳預(yù)覽原理,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

JS是什么

JS是JavaScript的簡(jiǎn)稱,它是一種直譯式的腳本語言,其解釋器被稱為JavaScript引擎,是瀏覽器的一部分,主要用于web的開發(fā),可以給網(wǎng)站添加各種各樣的動(dòng)態(tài)效果,讓網(wǎng)頁更加美觀。

追根溯源

設(shè)想

一開始,按照我的思路,預(yù)覽可能是這么來實(shí)現(xiàn)的。本地選中一張圖片,嵌入html的同時(shí)會(huì)顯示圖片的本地的絕對(duì)路徑,然后通過js簡(jiǎn)單的進(jìn)行設(shè)置,應(yīng)該就可以實(shí)現(xiàn)預(yù)覽效果了。

但是實(shí)際上,目前只有低版本的IE瀏覽器才能實(shí)現(xiàn)這么個(gè)效果。究其原因是瀏覽器廠商為了進(jìn)一步強(qiáng)化安全,限制了file標(biāo)簽直接讀取本地路徑的能力,在HTML5下只有通過FileReader的API來實(shí)現(xiàn)這一需求了。
比如對(duì)于CSDN寫博客的時(shí)候上傳一張圖片,得到的只會(huì)是一個(gè)fakepath。有圖為證:

js怎么實(shí)現(xiàn)圖片上傳預(yù)覽原理

原理

FileReader就是html5為我們提供的讀取文件的api。它的作用就是把文本流按指定格式讀取到緩存,以供js調(diào)用。

FileReader有四種讀取文件的方式:
 1.readAsBinaryString讀取為二進(jìn)制碼

 2.readAsDataURL讀取為 DataURL

 3.readAsText讀取為文本

 4.readAsArrayBuffer

根據(jù)本次實(shí)現(xiàn)的目標(biāo),使用第二種方式即可。img標(biāo)簽的src就是這個(gè)圖片的編碼后的DataURL。如圖所示:

js怎么實(shí)現(xiàn)圖片上傳預(yù)覽原理

DataURL淺析

DataURL 說來可是有很多內(nèi)容要研究的,但是這次用的比較淺顯,就把基礎(chǔ)的了解下就行了。

格式

DataURL有其固定的格式,如下:

data:[文件格式];base64,[文本流base64編碼]。

舉個(gè)例子:
 ?jpg格式: data:image/jpeg;base64,/9j/4...
 ?png格式: data:image/png;base64,iVBORw...
 ?gif格式: data:image/gif;base64,R0lGOD... 

?png格式的圖片編碼信息 

js怎么實(shí)現(xiàn)圖片上傳預(yù)覽原理

預(yù)覽實(shí)現(xiàn)

好了,弄明白了這些原理性的東西,就可以著手進(jìn)行實(shí)現(xiàn)了。

HTML

<form action="#" method="POST">
 <legend>
 圖片上傳
 </legend>
 <fieldset>
 <input type="file" name="pic1" id="pic1" onchange="preview(this)" multiple="multiple"
 accept="image/x-png, image/jpg, image/jpeg, image/gif">
 <br><br>
 </fieldset>
 <input type="button" value="上傳">
</form>
<div id="container">


</div>

在代碼中使用了Html5的一些新特性。用來過濾待上傳的圖片格式。

JavaScript控制

接下來就是預(yù)覽功能的實(shí)現(xiàn)了。目標(biāo)就是將圖片轉(zhuǎn)換成DataURL,然后對(duì)預(yù)覽區(qū)進(jìn)行子元素的添加操作。

<script>
 var msg = "您可以上傳png, jpg, 或者gif格式的圖片";
 var filter = {
 "jpeg": "/9j/4",
 "gif": "R0lGOD",
 "png": "iVBORw"
 };
 function preview(file) {
 var container = document.getElementById("container");
 container.innerHTML = "";
 if (window.FileReader) {
 for (var index=0, f; f = file.files[index]; index++) {

 var filereader = new FileReader();
 filereader.onload = function (event) {
 var srcpath = event.target.result;
 if (!validateImg(srcpath)) {
 console.log("H5"+msg);
 } else {
 showPreviewImage(srcpath);
 }
 };
 filereader.readAsDataURL(f);
 }
 } else {
 if (!/\.jpg$|\.png$|\.gif$/i.test(file.value)) {
 console.log("原生"+msg);
 } else {
 showPreviewImage(file.value);
 }
 }
 }

 function validateImg(data) {
 console.log(data);
 var pos = data.indexOf(",") + 1;
 for (var e in filter) {
 if (data.indexOf(filter[e]) === pos) {
 return e;
 }
 }
 return null;
 }

 function showPreviewImage(src) {
 console.log(src);


 var img = document.createElement('img');
 img.src = src;
 img.style = "width:64px;height:auto;"
 container.appendChild(img);
 }

</script>

預(yù)覽效果

總的來說代碼就算是完成了,接下來看下實(shí)現(xiàn)的效果。由于沒有設(shè)置樣式,所以看起來很簡(jiǎn)陋,有興趣的自己用樣式控制一下即可。

js怎么實(shí)現(xiàn)圖片上傳預(yù)覽原理

打包封裝

簡(jiǎn)易封裝

為了方便實(shí)用,特使用原生JavaScript封裝了一個(gè)這樣的組件。詳細(xì)代碼如下:

/**
 * Created by biao on 2017/7/10.
 * Description: A simple tool for previewing images for uploading.
 * Blog: http://blog.csdn.net/marksinoberg
 * GitHub: https://github.com/guoruibiao
 */

function ImgPrevirewer(config) {

 /**
 * The tag ID for upload images.
 */
 this.fileId = config.fileId;

 /**
 * tip for error message.
 * @type {string}
 */
 this.tip = config.tip;
 /**
 * The ID for the container which contains img tags.
 * @type {string}
 */
 this.containerId = config.containerId;
 /**
 * CSS style for previewing imgs.
 * @type {string}
 */
 this.imgStyle = config.imgStyle;

 /**
 * 過濾圖片格式,可進(jìn)行相對(duì)應(yīng)的刪減操作。
 * @type {{jpeg: string, gif: string, png: string}}
 */
 this.filter = {
 /**
 * jpg或者jpeg格式的圖片。
 */
 "jpeg": "/9j/4",
 /**
 * gif格式的圖片。
 */
 "gif": "R0lGOD",
 /**
 * PNG格式的圖片。
 */
 "png": "iVBORw"
 };


 /**
 * 開始預(yù)覽。自動(dòng)調(diào)用原生JavaScript實(shí)現(xiàn)相關(guān)元素的定位以及渲染。
 */
 this.preview = function () {
 var file = document.getElementById(this.fileId);
 var container = document.getElementById(this.containerId);
 container.innerHTML = "";
 /**
 * 防止內(nèi)部作用域覆蓋問題。
 * @type {ImgPrevirewer}
 */
 var that = this;
 // HTML5 需要使用FileReader的相關(guān)API來讀取本地?cái)?shù)據(jù)。
 if (window.FileReader) {
 // 針對(duì)多個(gè)上傳文件批量處理。
 for (var index = 0, f; f = file.files[index]; index++) {
 var filereader = new FileReader();
 filereader.onload = function (event) {
 var srcpath = event.target.result;
 if (!that.validateImg(srcpath)) {
 console.log(this.tip);
 } else {
 that.showPreviewImg(srcpath);
 }
 };
 filereader.readAsDataURL(f);
 }
 } else {
 // 低版本降級(jí)處理。
 if (!/\.jpg$|\.png$|\.gif$/i.test(file.value)) {
 console.log(this.tip);
 } else {
 that.showPreviewImg(file.value);
 }
 }
 }


 /**
 * 根據(jù)圖片的base64編碼格式查看圖片是否符合要求。
 * @param data 編碼后的圖片數(shù)據(jù)。
 * @returns {*}
 */
 this.validateImg = function (data) {
 var pos = data.indexOf(",") + 1;
 for (var e in this.filter) {
 if (data.indexOf(this.filter[e]) === pos) {
 return e;
 }
 }
 return null;
 }

 /**
 * 開始實(shí)現(xiàn)對(duì)圖片的預(yù)覽,根據(jù)this.imgStyle進(jìn)行相關(guān)渲染操作。
 * @param src
 */
 this.showPreviewImg = function (src) {
 var img = document.createElement('img');
 img.src = src;
 img.style = this.imgStyle;
 container.appendChild(img);
 }


}

使用方式

下面來一個(gè)簡(jiǎn)單的“模板式”使用技巧。

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Test</title>
 <script src="img-previewer.js"></script>
</head>
<body>
<input type="file" id="file" multiple onchange="preview()">
<div id="container">

</div>

<script>

 function preview(){
 var config = {
 tip: "請(qǐng)上傳格式為png, gif或者jpg的圖片",
 fileId: "file",
 containerId: "container",
 imgStyle: "width:320px;height:auto;border-radius:64%;"
 }
 var previewer = new ImgPrevirewer(config);
 previewer.preview();
 }

</script>
</body>
</html>

測(cè)試

為了保證這個(gè)組件的穩(wěn)定性,接下來來個(gè)簡(jiǎn)單的測(cè)試。

首先是在Chrome瀏覽器上,發(fā)現(xiàn)可以正常工作。

js怎么實(shí)現(xiàn)圖片上傳預(yù)覽原理

接下來是在Edge瀏覽器上的測(cè)試。(發(fā)現(xiàn)樣式不兼容)

js怎么實(shí)現(xiàn)圖片上傳預(yù)覽原理

不出所料,IE系的瀏覽器樣式都沒能兼容。

js怎么實(shí)現(xiàn)圖片上傳預(yù)覽原理

最終發(fā)現(xiàn),Chrome等WebKit內(nèi)核的瀏覽器可以完美支持,對(duì)于微軟系瀏覽器而言,功能可以滿足,但是樣式上不兼容,這點(diǎn)可以通過特定的瀏覽器頭來實(shí)現(xiàn),不再過多敘述。

以上是“js怎么實(shí)現(xiàn)圖片上傳預(yù)覽原理”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

js
AI