Ajax異步文件上傳與NodeJS express服務(wù)端處理
為了避免在實現(xiàn)簡單的異步文件上傳功能時候引入一個第三方庫文件的尷尬情形(庫文件可能造成多余的開銷,拉低應(yīng)用加載速度,尤其是在引入庫文件之后僅使用其中一兩個功能的情況下,性價比極低),最近了解了一下文件異步上傳的實現(xiàn)原理,順帶看了看進(jìn)度條、圖片預(yù)覽等功能的實現(xiàn),做一點簡單的整理。
文件上傳
HTML結(jié)構(gòu)如下,一個file input和一個button。當(dāng)點擊“上傳”按鈕的時候,將file input選中的文件上傳到服務(wù)器。
<input type="file" name="file" id="file" /> <button id="upload">上傳</button>
以下是“上傳”按鈕的點擊事件處理器,點擊按鈕之后通過一個XMLHttpRequest對象來實現(xiàn)發(fā)送異步請求。上傳的內(nèi)容為文件,因此還需要用到FormData對象,F(xiàn)ormData可以js里面創(chuàng)建表單對象,將file input的文件append到FormData對象中,最后調(diào)用XHR對象的send()方法將表單數(shù)據(jù)發(fā)送出去即可。
var file = document.querySelector('#file');
var upload = document.querySelector('#upload');
var xhr = new XMLHttpRequest();
// 點擊上傳
function uploadFile(event) {
var formData = new FormData();
formData.append('test-upload', file.files[0]);
xhr.onload = uploadSuccess;
xhr.open('post', '/upload', true);
xhr.send(formData);
}
// 成功上傳
function uploadSuccess(event) {
if (xhr.readyState === 4) {
console.log(xhr.responseText);
}
}
上傳進(jìn)度
在進(jìn)行文件上傳的時候,xhr對象會有一個upload屬性,會提供一個progress事件,在相應(yīng)的事件處理器里面通過事件對象可以知道當(dāng)前的上傳進(jìn)度,利用這個特點可以很方便地實現(xiàn)進(jìn)度條或者進(jìn)度提示。
<input type="file" name="file" id="file" /> <button id="upload">上傳</button> <span id="progress">0%</span>
var progress = document.querySelector('#progress');
// 點擊上傳
function uploadFile(event) {
var formData = new FormData();
formData.append('test-upload', file.files[0]);
xhr.onload = uploadSuccess;
xhr.upload.onprogress = setProgress;
xhr.open('post', '/upload', true);
xhr.send(formData);
}
// 進(jìn)度條
function setProgress(event) {
if (event.lengthComputable) {
var complete = Number.parseInt(event.loaded / event.total * 100);
progress.innerHTML = complete + '%';
}
}
圖片預(yù)覽
上傳圖片的時候可以利用FileReader對象來實現(xiàn)圖片預(yù)覽。FileReader可以異步讀取用戶電腦上的文件,將file input選中的文件傳給FileReader,讀取之后取得文件的URL并設(shè)置為image元素的src即可讓選中的圖片文件顯示出來。
<input type="file" name="file" id="file" /> <button id="upload">上傳</button> <span id="progress">0</span> <img id="image" src="" width="200" />
var file = document.querySelector('#file');
file.addEventListener('change', previewImage, false);
// 圖片預(yù)覽
function previewImage(event) {
var reader = new FileReader();
reader.onload = function (event) {
image.src = event.target.result;
};
reader.readAsDataURL(event.target.files[0]);
}
服務(wù)端處理
使用express搭建一個簡單的NodeJS服務(wù)端,提供上傳文件的接口。express要支持文件上傳需要用到中間件,在express官網(wǎng)上有很多介紹。這里我使用的是multer中間件,下面是簡單的使用示例。upload.single表示這個接口接受的上傳文件數(shù)量為1個,'test-upload'限制了上傳的表單數(shù)據(jù)的鍵為'test-upload'(formData.append(‘test-upload', file.files[0]);)。經(jīng)過這個中間件處理之后,通過req.file可以訪問到文件的相關(guān)信息,上傳的文件存放在uploads文件夾中。
const upload = require('multer')({ dest: 'uploads/' });
app.post('/upload', upload.single('test-upload'), (req, res) => {
// 沒有附帶文件
if (!req.file) {
res.json({ ok: false });
return;
}
// 輸出文件信息
console.log('====================================================');
console.log('fieldname: ' + req.file.fieldname);
console.log('originalname: ' + req.file.originalname);
console.log('encoding: ' + req.file.encoding);
console.log('mimetype: ' + req.file.mimetype);
console.log('size: ' + (req.file.size / 1024).toFixed(2) + 'KB');
console.log('destination: ' + req.file.destination);
console.log('filename: ' + req.file.filename);
console.log('path: ' + req.file.path);
});

由輸出可以看到,文件的命名使用一個哈希值表示,并且去除了后綴名,想要保持文件的原有的命名格式,需要再通過fs對文件進(jìn)行改名。
app.post('/upload', upload.single('test-upload'), (req, res) => {
// 沒有附帶文件
if (!req.file) {
res.json({ ok: false });
return;
}
// 輸出文件信息
console.log('====================================================');
console.log('fieldname: ' + req.file.fieldname);
console.log('originalname: ' + req.file.originalname);
console.log('encoding: ' + req.file.encoding);
console.log('mimetype: ' + req.file.mimetype);
console.log('size: ' + (req.file.size / 1024).toFixed(2) + 'KB');
console.log('destination: ' + req.file.destination);
console.log('filename: ' + req.file.filename);
console.log('path: ' + req.file.path);
// 重命名文件
let oldPath = path.join(__dirname, req.file.path);
let newPath = path.join(__dirname, 'uploads/' + req.file.originalname);
fs.rename(oldPath, newPath, (err) => {
if (err) {
res.json({ ok: false });
console.log(err);
} else {
res.json({ ok: true });
}
});
});
完整代碼
ajax異步文件上傳、進(jìn)度顯示、圖片預(yù)覽
<input type="file" name="file" id="file" /> <button id="upload">上傳</button> <span id="progress">0</span> <img id="image" src="" width="200" />
(function () {
'use strict';
var file = document.querySelector('#file');
var upload = document.querySelector('#upload');
var progress = document.querySelector('#progress');
var image = document.querySelector('#image');
var xhr = new XMLHttpRequest();
upload.addEventListener('click', uploadFile, false);
file.addEventListener('change', previewImage, false);
// 點擊上傳
function uploadFile(event) {
var formData = new FormData();
formData.append('test-upload', file.files[0]);
xhr.onload = uploadSuccess;
xhr.upload.onprogress = setProgress;
xhr.open('post', '/upload', true);
xhr.send(formData);
}
// 成功上傳
function uploadSuccess(event) {
if (xhr.readyState === 4) {
console.log(xhr.responseText);
}
}
// 進(jìn)度條
function setProgress(event) {
if (event.lengthComputable) {
var complete = Number.parseInt(event.loaded / event.total * 100);
progress.innerHTML = complete + '%';
}
}
// 圖片預(yù)覽
function previewImage(event) {
var reader = new FileReader();
reader.onload = function (event) {
image.src = event.target.result;
};
reader.readAsDataURL(event.target.files[0]);
}
})();
express服務(wù)器提供文件上傳接口
const express = require('express');
const upload = require('multer')({ dest: 'uploads/' });
const path = require('path');
const fs = require('fs');
const port = 8080;
let app = express();
app.set('port', port);
// index.html, index.js放在static文件夾中
app.use(express.static(path.join(__dirname, 'static')));
app.get('*', (req, res) => {
res.redirect('index.html');
});
app.post('/upload', upload.single('test-upload'), (req, res) => {
// 沒有附帶文件
if (!req.file) {
res.json({ ok: false });
return;
}
// 輸出文件信息
console.log('====================================================');
console.log('fieldname: ' + req.file.fieldname);
console.log('originalname: ' + req.file.originalname);
console.log('encoding: ' + req.file.encoding);
console.log('mimetype: ' + req.file.mimetype);
console.log('size: ' + (req.file.size / 1024).toFixed(2) + 'KB');
console.log('destination: ' + req.file.destination);
console.log('filename: ' + req.file.filename);
console.log('path: ' + req.file.path);
// 重命名文件
let oldPath = path.join(__dirname, req.file.path);
let newPath = path.join(__dirname, 'uploads/' + req.file.originalname);
fs.rename(oldPath, newPath, (err) => {
if (err) {
res.json({ ok: false });
console.log(err);
} else {
res.json({ ok: true });
}
});
});
app.listen(port, () => {
console.log("[Server] localhost:" + port);
});
以上就是本文的全部內(nèi)容,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,同時也希望多多支持腳本之家!
- node+axios實現(xiàn)服務(wù)端文件上傳示例
- 利用node+koa+axios實現(xiàn)圖片上傳和回顯功能
- 詳解Vue+axios+Node+express實現(xiàn)文件上傳(用戶頭像上傳)
- nodejs+express實現(xiàn)文件上傳下載管理網(wǎng)站
- nodejs基于express實現(xiàn)文件上傳的方法
- 詳解nodejs實現(xiàn)本地上傳圖片并預(yù)覽功能(express4.0+)
- Nodejs+express+html5 實現(xiàn)拖拽上傳
- 基于nodejs+express(4.x+)實現(xiàn)文件上傳功能
- 使用express+multer實現(xiàn)node中的圖片上傳功能
- 使用nodejs+express實現(xiàn)簡單的文件上傳功能
- Nodejs進(jìn)階:基于express+multer的文件上傳實例
- NodeJS實現(xiàn)圖片上傳代碼(Express)
- node+express+axios實現(xiàn)單文件上傳功能
相關(guān)文章
JavaScript實現(xiàn)網(wǎng)頁電子時鐘
這篇文章主要為大家詳細(xì)介紹了JavaScript實現(xiàn)網(wǎng)頁電子時鐘,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-06-06
Javascript使用SWFUpload進(jìn)行多文件上傳
本篇文章主要解釋了使用SWFUpload進(jìn)行多文件上傳,這里整理了詳細(xì)的代碼,有需要的可以了解一下。2016-11-11
file-loader打包圖片文件時路徑錯誤輸出為[object-module]的解決方法
這篇文章主要介紹了file-loader打包圖片文件時路徑錯誤輸出為[object-module]的解決方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01
JavaScript清空數(shù)組元素的兩種方法簡單比較
這篇文章主要介紹了JavaScript清空數(shù)組元素的兩種方法簡單比較,羅列了幾種常見的情況javascript數(shù)組的方法,并且比較了其中的兩種常見方法,具有一定參考借鑒價值,需要的朋友可以參考下2015-07-07
一文學(xué)會用JS判斷文字是否被省略(ellipsis)
這篇文章主要給大家介紹了用JS如何判斷文字被省略ellipsis,CSS幫我們搞定了省略,但是JS并不知道文本什么時候被省略了,所以我們得通過JS來計算,接下來,我將介紹2種方法來實現(xiàn)JS計算省略,需要的朋友可以參考下2023-08-08
Microsfot .NET Framework4.0框架 安裝失敗的解決方法
今天在安裝.NET Framework 4.0,安裝了半天結(jié)果提示未安裝成功,提示原因是服務(wù)未啟動了,error code: (0x80070643), "安裝時發(fā)生嚴(yán)重錯誤 "2013-08-08
通過js動態(tài)創(chuàng)建標(biāo)簽,并設(shè)置屬性方法
下面小編就為大家分享一篇通過js動態(tài)創(chuàng)建標(biāo)簽,并設(shè)置屬性方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-02-02

