let nodemailer = require('nodemailer');
let transporter = nodemailer.createTransport({
'host': 'smtp.qq.com', // 主機(jī)
'secureConnection': true, // 使用 SSL
'service': 'qq',
'port': 465, // SMTP 端口
'auth': {
'user': '您的QQ賬號@qq.com', // 賬號
'pass': '上一步生成的授權(quán)碼' // 授權(quán)碼
}
});
let mailContent = {
from: '"NBA 官網(wǎng)" <您的QQ賬號@qq.com>', // 發(fā)件人地址
to: 'liutao0723@163.com', // 收件人地址
subject: 'Hello, world!', // 主題
// 發(fā)送text或者h(yuǎn)tml格式
// text: 'Hello 我是火星黑洞', // plain text body
html: '<b>Hello 我是火星黑洞。。。。。</b>' // html body
};
// 發(fā)送郵件
transporter.sendMail(mailContent, (err, info) => {
if (err) {
console.log('出錯了', err)
} else {
console.log('發(fā)送成功,請前往發(fā)送者的郵箱查看已發(fā)送郵收件者的已接收郵箱查看')
}
});
件上傳如果加上進(jìn)度條會有更好的用戶體驗(尤其是中大型文件),本文使用Nodejs配合前端完成這個功能。
前端我們使用 FormData 來作為載體發(fā)送數(shù)據(jù)。
<input type="file" id="file" />
<!-- 進(jìn)度條 -->
<progress id="progress" value="0" max="100"></progress>
// 獲取 input file 的 dom 對象
const inputFile = document.querySelector('#file');
// 監(jiān)聽 change 事件
inputFile.addEventListener('change', function() {
// 使用 formData 裝載 file
const formData = new FormData();
formData.append('file', this.files[0]);
// 上傳文件
upload(formData);
})
下面我們實現(xiàn)upload 方法。
const upload = ( formData ) => {
const xhr = new XMLHttpRequest();
// 監(jiān)聽文件上傳進(jìn)度
xhr.upload.addEventListener('progress', function(e) {
if (e.lengthComputable) {
// 獲取進(jìn)度
const progress = Math.round((e.loaded * 100) / e.total);
document.querySelector('#progress').setAttribute('value', progress);
}
},false);
// 監(jiān)聽上傳完成事件
xhr.addEventListener('load', ()=>{
console.log('上傳完成')
}, false);
xhr.open('post', 'http://127.0.0.1:3000/upload');
xhr.send(formData);
}
jQuery 目前的使用量依然龐大,那么使用 jQuery 的 ajax 如何監(jiān)聽文件上傳進(jìn)度呢:
const upload = ( formData ) => {
$.ajax({
type: 'post',
url: 'http://127.0.0.1:3000/upload',
data: formData,
// 不進(jìn)行數(shù)據(jù)處理和內(nèi)容處理
processData: false,
contentType: false,
// 監(jiān)聽 xhr
xhr: function() {
const xhr = $.ajaxSettings.xhr();
if (xhr.upload) {
xhr.upload.addEventListener('progress', e => {
const { loaded, total } = e;
var progress = (loaded / total) * 100;
document.querySelector('#progress').setAttribute('value', progress);
},
false
);
return xhr;
}
},
success: function(response) {
console.log('上傳成功');
}
});
}
axios 使用量非常大,用它監(jiān)聽文件上傳更簡單,代碼如下:
const upload = async ( formData ) => {
let config = {
// 注意要把 contentType 設(shè)置為 multipart/form-data
headers: {
'Content-Type': 'multipart/form-data'
},
// 監(jiān)聽 onUploadProgress 事件
onUploadProgress: e => {
const {loaded, total} = e;
// 使用本地 progress 事件
if (e.lengthComputable) {
let progress = loaded / total * 100;
document.querySelector('#progress').setAttribute('value', progress);
}
}
};
const { status } = await axios.post('http://127.0.0.1:3000/upload', formData, config);
if (res.status === 200) {
console.log('上傳完成');
}
}
這部分比較簡單,其實就是單純的文件上傳,我們用 Koa 來實現(xiàn).
這里使用 koa2,安裝以下依賴包:
const Koa = require('koa');
const Router = require('@koa/router');
const koaBody = require('koa-body');
const path = require('path');
const fs = require('fs');
const cors = require('@koa/cors');
const app = new Koa();
const router = new Router();
router.all('/upload', async ctx => {
// 處理文件上傳
const res = await dealFile(ctx);
res && (ctx.body = {
status: 200,
msg: 'complete'
});
});
// 中間件部分
app.use(cors());
app.use(
koaBody({
multipart: true,
formidable: {
maxFileSize: 2000 * 1024 * 1024 //最大2G
}
})
);
app.use(router.routes());
app.use(router.allowedMethods());
app.listen(3000);
出于性能考慮,操作file 毫無疑問要使用stream。 我們要監(jiān)聽文件流end事件,由于無法在事件回調(diào)里返回響應(yīng),因為會報 404,所以需要使用 Promise 來封裝一下,然后用 async、await
const dealFile = ctx => {
const { file } = ctx.request.files;
const reader = fs.createReadStream(file.path);
const writer = fs.createWriteStream(
// 文件上傳到 image 文件夾中
path.resolve(__dirname, './image', file.name)
);
return new Promise((resove, reject) => {
reader.pipe(writer);
reader.on('end', () => {
resove(true);
});
reader.on('error', err => {
throw err;
})
});
};
到這里就全部完成了。
這里注意一下:前端監(jiān)聽文件進(jìn)度不需要后端有什么特殊處理,后端僅僅是做了文件流的寫入而已。
作者:Ve
鏈接:https://juejin.im/post/5e7ca27df265da42ac0294e5
來源:掘金
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。
者:林克 來源:JavaScript
如果你是一名希望掌握一些后端技能的前端開發(fā)人員,那么在開始構(gòu)建 Node.js 應(yīng)用程序之前,將不必花費大量時間學(xué)習(xí) JavaScript。但是,如果你是一個初學(xué)者,希望在盡可能短的時間內(nèi)掌握 Node.js,那么在深入研究 Node.js 環(huán)境之前,必須學(xué)習(xí)以下概念。
在Node.js中,將面對大量的異步編程,為此,建議學(xué)習(xí)以下概念。
Node Package Manager 擁有大量的軟件包,在我們開發(fā)需要大量依賴關(guān)系的應(yīng)用程序時,使用 NPM 包管理程序?qū)⒎浅7奖恪?/p>
Git,GitHub
了解有關(guān)如何使用傳輸協(xié)議傳輸數(shù)據(jù)的基礎(chǔ)知識將使您成為更好的Node.js開發(fā)人員,對HTTP和HTTPS的工作原理有很好的了解。HTTPS使用稱為傳輸層安全性(TLS)的加密協(xié)議來加密通信。在后端環(huán)境中有很多東西要學(xué)習(xí),如果您不了解網(wǎng)絡(luò)的工作原理,可能會有些困惑,有以下幾種請常見的求方法用于網(wǎng)絡(luò)上的基本通信:
以下框架不需要全部精通,擇一學(xué)習(xí)即可。
關(guān)系型數(shù)據(jù)庫
NoSQL數(shù)據(jù)庫
ElasticSearch
一個基于Apache Lucene并使用Java開發(fā)的搜索和分析引擎。使用ElasticSearch,您可以實時存儲和分析大量數(shù)據(jù)。當(dāng)它搜索索引而不是搜索文本時,ElasticSearch也實現(xiàn)了出色的搜索性能。它的核心是使用基于結(jié)構(gòu)的文檔,而不是廣泛的REST API附帶的用于存儲和搜索數(shù)據(jù)的表和模式。您可以將ElasticSearch視為處理JSON請求并向您返回JSON數(shù)據(jù)的服務(wù)器。
Solr
它提供了相當(dāng)高級的實時搜索功能,例如字段搜索,布爾查詢,階段查詢,模糊查詢,拼寫檢查,自動完成等等。
Memory Cache
這種技術(shù)通常也稱為緩存,因為在大多數(shù)情況下,緩存與服務(wù)器中的內(nèi)存相關(guān)聯(lián)。在這種技術(shù)中,服務(wù)器內(nèi)存的一部分用作緩存,我們在其中存儲減少應(yīng)用程序中的網(wǎng)絡(luò)調(diào)用所需的所有數(shù)據(jù)。在Node.js中,我們擁有node-cache 和 memory-cache作為一些出色的庫來處理nodejs服務(wù)器中的內(nèi)存緩存。
Distributed Cache
在這種緩存技術(shù)中,我們將多個網(wǎng)絡(luò)的內(nèi)存合并到一個內(nèi)存數(shù)據(jù)存儲中,之后將其用作最終數(shù)據(jù)緩存以證明對數(shù)據(jù)的快速訪問。此技術(shù)尤其適用于大量數(shù)據(jù),并且通過向群集添加更多服務(wù)器內(nèi)存,大量的網(wǎng)絡(luò)調(diào)用同時允許增量擴(kuò)展和擴(kuò)展。關(guān)于分布式緩存,Redis是最著名的事情之一。
使用模板引擎,我們可以在應(yīng)用程序中使用靜態(tài)模板文件,而在運行時,該模板引擎將模板文件中的變量替換為實際值,然后將模板轉(zhuǎn)換為發(fā)送給客戶端的HTML文件。下面列出了一些流行的模板引擎。
如果您只是作為后端開發(fā)人員起步,那么在了解Socket.IO中的實時通信方面有很多事情,實時通信背后的主要邏輯就在于客戶端和服務(wù)器之間。它允許流動雙向客戶端與服務(wù)器之間的數(shù)據(jù),你能想到的雙向數(shù)據(jù)流的數(shù)據(jù)的兩個終端之間的同步流程,實現(xiàn)實時通訊的行為,這類行為被啟用時,客戶端在瀏覽器中具有Socket.IO以及與Socket.IO軟件包集成的服務(wù)器。并且數(shù)據(jù)可以以JSON請求的形式發(fā)送。
單元測試框架
在單元測試中,我們隔離地測試各個單元/組件,其中單元可以是應(yīng)用程序中代碼中可測試的最小部分。在Node.js中,下面列出了幾種常見的單元測試框架:
*請認(rèn)真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。