1. 準備工作
因為要發送Ajax請求,而Ajax技術的運行需要網站環境,因此其中一個解決方案是,將頁面作為網站的靜態資源暴露出來,然后通過瀏覽器進行訪問.
1.1 靜態資源
- 使用express將public下面的資源暴露出來
- 在根目錄下面新建一個
public
文件夾和一個app.js
文件
// app.js
const express = require('express');
const path = require('path')
const app = express();app.use(express.static(path.join(__dirname, 'public')))app.listen(3000, () =>{console.log('localhost:3000');
})
- 在public下新建一個
01.html
<!-- 01.html -->
<body><h2>通過靜態資源訪問 01.html</h2>
</body>
- 命令行輸入
nodemon app.js
(注意目錄), 打開瀏覽器訪問localhost:3000/01.html
2. 文件上傳的進度條展示
- 下面的樣式使用到了 bootstrap. 不導入也沒關系
- 在文件上傳的過程中,可以將上傳的進度實時展示出來,這樣用戶的體驗感會提升
- 核心代碼如下:
file.onchange = function () {xhr.upload.onprogress = function (ev) {console.log( (ev.loaded / ev.total) * 100 + '%' );}
}
- 思路如下:
1.在input框下面有一個顯示進度條的元素
2.點擊文件上傳后,會觸發file.onchange
事件
3.在文件傳到服務器(FormData
)的過程中會持續觸發xhr.upload.onprogress
事件.
4.在onprogress
事件中,會有一個ev
對象,它保留著,文件上傳的信息
5.利用文件上傳的信息,算出上傳的進度,顯示在網頁中
2.1 [栗子] - 上傳的表單控件
<div class="container"><div class="form-group"><label>請選擇文件</label><input type="file" id="file" /><br /><div class="progress"><div class="progress-bar" style="width: 0%;" id="bar">0%</div></div></div>
</div>
2.2 [栗子] - 上傳的代碼(前端)
<script>var file = document.getElementById('file');var bar = document.getElementById('bar');file.onchange = function () {// 文件上傳使用到 FormData構造函數var formData = new FormData();// 'attrName'方便后面使用.formData.append('attrName', this.files[0]);// 上傳的信息準備好了,接下來準備Ajax請求var xhr = new XMLHttpRequest();xhr.open('post','http://localhost:3000/uploads');// 文件上傳的過程中,會持續觸發onprogress事件xhr.upload.onprogress = function(ev){var result = (ev.loaded / ev.total) * 100 + '%';// 算出上傳的百分比,并將值放在bar中bar.style.width = result;bar.innerHTML = result;}xhr.send(formData);xhr.onload = function () {if(xhr.status == 200 ){console.log(xhr.responseText)}}}
</script>
2.3 [栗子] - 上傳的代碼(服務端)
// 服務端使用formidable解析參數
const formidable = require('formidable');
const path = require('path')
app.post('/uploads', (req, res)=>{// 創建接收的實例const form = new formidable.IncomingForm();// 設置文件的存儲位置form.uploadDir = path.join(__dirname, 'public', 'uploads');// 保留后綴名form.keepExtensions = true;// 解析客戶端的數據form.parse(req, (err, fields ,files) =>{res.send({ path: files.attrName.path.split('public')[1] })})
})
3. 文件上傳圖片即使預覽
- 以前寫過一篇放在前端內存中的
- 這一篇是:
- 將圖片通過
FormData
傳遞到服務端 - 然后服務端將圖片保存在靜態資源中,并將資源的地址返回給客戶端
- 然后客戶端訪問這個靜態資源進行顯示
- 將圖片通過
3.1 [栗子] - 前端dom元素如下
<div class="container"><div class="form-group"><label>請選擇</label><input type="file" id="file" /><!-- 用來顯示上傳的圖片 --><div class="padding" id="box"></div></div>
</div>
3.2 [栗子] - 前端上傳文件的代碼
<script>var file = document.getElementById('file');var box = document.getElementById('box');file.onchange = function () {var formData = new FormData();formData.append('attrName', this.files[0]);var xhr = new XMLHttpRequest();xhr.open('post', 'http://localhost:3000/uploads')xhr.send(formData);xhr.onload = function() {if(xhr.status == 200) {var result = JSON.parse(xhr.responseText);var img = document.createElement('img');img.src = result.path;img.onload = function() {box.appendChild(img)}}}}
</script>
3.3[栗子] - 后端代碼
// 服務端使用formidable解析參數
const formidable = require('formidable');
const path = require('path')
app.post('/uploads', (req, res)=>{// 創建接收的實例const form = new formidable.IncomingForm();// 設置文件的存儲位置form.uploadDir = path.join(__dirname, 'public', 'uploads');// 保留后綴名form.keepExtensions = true;// 解析客戶端的數據form.parse(req, (err, fields ,files) =>{res.send({ path: files.attrName.path.split('public')[1] })})
})
4. 參考
源代碼