如何利用原生JS實現(xiàn)圖片預(yù)覽加上傳(前后端交互)
前言
最近在寫vue項目的時候發(fā)現(xiàn)了個Vant的一個upload的圖片上傳的組件,就好奇了一下下,于是萌生了一個自己手寫一個圖片上傳的組件的想法,您猜怎么著,還真給我實現(xiàn)了,那今天就和大家分享一下,大家有興趣的可以了解一下啦,寫進項目中可能會是個加分點哦!!
我們知道文件上傳是需要前后端交互的,所以我這邊給出前后端代碼。 文件上傳大致分為以下幾個步驟
- 前端文件選擇上傳的文件類型
- 拿到文件信息
- 將選擇的文件(視頻或圖片)在前端頁面預(yù)覽出來
- 將文件發(fā)上傳到后端服務(wù)器
- 客戶端能夠訪問到上傳到服務(wù)器端的文件
效果大致如下
前端代碼
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> .button{ margin-right: 20px; } #preview { display: flex; flex-wrap: wrap; width: 1500px; padding: 0 10px; justify-content: start; } .icon-po { overflow: hidden; position: relative; width: 300px; height: 300px; margin-right: 20px; margin-top: 20px; } .icon-close { position: absolute; right: 5%; top: 5%; width: 30px; height: 30px; border-radius: 50%; background-color: red; color: #fff; font-size: 12px; display: flex; align-items: center; justify-content: center; } .pic{ width: 300px; height: 300px; } </style> </head> <body> 選擇文件(允許多文件): <input type="file" id="f1" multiple> //multiple開啟多選 <button type="button" class="button" id="btn-submit">預(yù)覽圖片</button> <button type="button" id="complate">上傳圖片</button> <div id="preview"></div> <br /> <script> let e = 0 let fd = new FormData() //文件傳輸一定要使用ForData對象 let fL = [] function submitUpload() { let fileList = document.getElementById('f1').files for (let i = 0; i < fileList.length; i++) { fL.push(fileList[i]) } //渲染出圖片 //FileReader 讀取文件的方式為readAsDataURL時會觸發(fā) function readAndPreview(file) { // 確保 `file.name` 符合我們要求的擴展名 if (/\.(jpe?g|png|gif|mp4)$/i.test(file.name)) { //FileReader 對象允許Web應(yīng)用程序異步讀取存儲在用戶計算機上的文件 //(或原始數(shù)據(jù)緩沖區(qū))的內(nèi)容 //這里是讀取到input返回出來的fileList中文件 var reader = new FileReader(); //該事件在FileReader對象讀取操作完成時觸發(fā) reader.addEventListener("load", function () { //創(chuàng)建出兩個div 一個用做父容器 一個做刪除按鈕 var div1 = document.createElement('div'); var div2 = document.createElement('div'); //創(chuàng)建一個Image Dom 用來做渲染圖片 var dom = new Image() //當(dāng)然要是想渲染視頻的話就創(chuàng)建一個video標簽就好啦 //給創(chuàng)建的Dom添加類名用于設(shè)計樣式 div1.className = 'icon-po' div2.className = 'icon-close' div2.innerHTML = 'X' dom.className = 'pic //給生成的每個圖片盒子添加index屬性 div1.index = div2.index = e e++ //給刪除按鈕添加上點擊事件 div2.onclick = (e) => { console.log(e.target.index) div1.remove() fL.splice(e.target.index, 1, "") console.log(fL); } //設(shè)置img的樣式 dom.width = 300; dom.height = 300; dom.title = file.name; //該 result屬性包含作為數(shù)據(jù)的數(shù)據(jù): URL將文件的數(shù)據(jù)表示為 base64 編碼的字符串。 dom.src = this.result; //將創(chuàng)建出的dom添加進對應(yīng)的dom中去 div1.appendChild(dom) div1.appendChild(div2) preview.appendChild(div1); }, false); //調(diào)用readAsDataURL()方法拿到result reader.readAsDataURL(file); } } //拿到input中的fileList中的文件對象進行渲染出圖片 if (fileList) { [].forEach.call(fileList, readAndPreview); } if (!fileList.length) { alert('請選擇文件') return } } function complate() { //篩選出未刪除的文件 fL.forEach(async (item) => { if (typeof item === "string") { console.log(item); } else { fd.append('files', item)//將沒有別刪除的文件加入到FormData對象中 } }) //向后端發(fā)送請求 let xhr = new XMLHttpRequest() xhr.open('POST', 'http://localhost:3007/', true) xhr.send(fd) xhr.onreadystatechange = function () { if (this.readyState == 4 && this.status == 200) { let obj = JSON.parse(xhr.responseText) console.log(obj); } } } document.getElementById('btn-submit').addEventListener('click', submitUpload) document.getElementById('complate').addEventListener('click', complate) </script> </body> </html>
后端代碼
/** * 服務(wù)入口 */ var koaStatic = require('koa-static'); var path = require('path'); var koaBody = require('koa-body'); var fs = require('fs'); var Koa = require('koa2'); var cors = require('koa2-cors') //解決跨域 var app = new Koa(); var port = process.env.PORT || '3007'; var uploadHost = `http://localhost:3001/uploads/`; app.use(cors()) app.use(koaBody({ //koa-body 是一個可以幫助解析 http 中 body 的部分的中間件,包括 json、表單、文本、文件等。 formidable: { //設(shè)置文件的默認保存目錄,不設(shè)置則保存在系統(tǒng)臨時目錄下 uploadDir: path.resolve(__dirname, './static') }, multipart: true // 支持文件上傳 })); app.use(koaStatic( //讓我們更加快速訪問服務(wù)中的靜態(tài)資源 path.resolve(__dirname, './static') )); //二次處理文件,修改名稱 app.use((ctx) => { console.log(ctx.request.files); var files = ctx.request.files.files;//得到上傳文件的數(shù)組 var result = []; console.log(files); let baseUrl = 'http://192.168.10.4:3007/' if (!Array.isArray(files)) {//單文件上傳容錯 files = [files]; } files && files.forEach(item => { var path = item.path.replace(/\\/g, '/'); var fname = item.name;//原文件名稱 var nextPath = path + fname; if (item.size > 0 && path) { //得到擴展名 var extArr = fname.split('.'); var ext = extArr[extArr.length - 1]; var nextPath = path + '.' + ext; //重命名文件 fs.renameSync(path, nextPath); console.log(baseUrl + nextPath.slice(nextPath.lastIndexOf('/') + 1)) result.push(baseUrl + nextPath.slice(nextPath.lastIndexOf('/') + 1)); } }); ctx.body = {//向前端返回圖片上傳后的地址 "fileUrl":`${JSON.stringify(result)}` }; }) app.listen(port, () => { console.log('服務(wù)已啟動3007'); })
總結(jié)
代碼我都做好詳細注釋啦,使用到的官方對象的作用我也給你總結(jié)出來了給你們偷個懶??!相信大家花點時間看一下就能懂啦,最后我再叨叨幾句~
- 前端
- js使用input type ="file"可以上傳文件
- 讀取文件完成后創(chuàng)建出幾個DOM用來預(yù)覽圖片,配置好相應(yīng)的功能需求
- FileReader 對象允許Web應(yīng)用程序異步讀取存儲在用戶計算機上的文件(或原始數(shù)據(jù)緩沖區(qū))的內(nèi)容,使用 [File] 或 [Blob] 對象指定要讀取的文件或數(shù)據(jù)。
- readAsDataURL 方法會讀取指定的 [Blob]/Blob) 或 [File] 對象。讀取操作完成的時候,[readyState] 會變成已完成DONE,并觸發(fā) loadend (en-US) 事件,同時 [result] 屬性將包含一個data:URL格式的字符串(base64編碼)以表示所讀取文件的內(nèi)容。
- FormData接口提供了一種方法來輕松構(gòu)造一組表示表單字段及其值的鍵/值對,然后可以使用該[XMLHttpRequest.send()]方法向后端發(fā)送文件。
- 后端
- 后端這里是使用Koa寫的
- 安裝koa2-cors防止跨域
- 安裝koa-body拿到前端傳來的文件,并存在相應(yīng)的目錄下
- 安裝Koa-static然后端更加方便的訪問到上傳的文件地址
到此這篇關(guān)于如何利用原生JS實現(xiàn)圖片預(yù)覽加上傳的文章就介紹到這了,更多相關(guān)JS實現(xiàn)圖片預(yù)覽上傳內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
uniapp自定義頁面跳轉(zhuǎn)loading的實現(xiàn)代碼
有些頁面加載起來比較慢,為了加強用戶體驗效果,所以一般都會做一個頁面加載等待的提示,頁面加載完成后消失,下面這篇文章主要給大家介紹了關(guān)于uniapp自定義頁面跳轉(zhuǎn)loading的實現(xiàn)代碼,需要的朋友可以參考下2023-06-06JavaScript實現(xiàn)的類字典插入或更新方法實例
這篇文章主要介紹了JavaScript實現(xiàn)的類字典插入或更新方法,實例分析了javascript針對類字典的插入與更新技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-07-07addeventlistener監(jiān)聽scroll跟touch(實例講解)
下面小編就為大家?guī)硪黄猘ddeventlistener監(jiān)聽scroll跟touch(實例講解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-08-08JS實現(xiàn)瀏覽器點擊下載圖片功能案例分析【親測有效】
這篇文章主要介紹了JS實現(xiàn)瀏覽器點擊下載圖片功能,對比分析了同源與不同源兩種解決方案,并以實際案例形式分析了不同源情況下針對文件點擊下載的具體實現(xiàn)技巧與相關(guān)注意事項,需要的朋友可以參考下2023-04-04js+canvas實現(xiàn)轉(zhuǎn)盤效果(兩個版本)
這篇文章主要為大家詳細介紹了兩個版本的js+canvas實現(xiàn)轉(zhuǎn)盤效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-09-09Javascript讀取上傳文件內(nèi)容/類型/字節(jié)數(shù)
這篇文章主要為大家詳細介紹了Javascript讀取上傳文件內(nèi)容/類型/字節(jié)數(shù),具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-04-04