現(xiàn)在node.js 使用的框架有 Express,koa 還有分別基于nest.js 和 egg.js 。據(jù)說nest.js 可以和 java 的 String 有得一比。
express 和 koa 屬于 個(gè)人或者玩具的東西,學(xué)習(xí)一下就好了。
后面兩個(gè)框架的話,都比較好.egg.js thinkphp 的影子[可能這就是我選擇egg.js的原因]
還有就是cnode 這個(gè)網(wǎng)站 兩個(gè)版本都有
egg.js 和 版本會比 express的版本 打開快那么幾毫秒。
如果做論壇什么的話
可以直接區(qū) github 上找cnode 這個(gè)作者算市不錯(cuò)了,把自己的 網(wǎng)站 業(yè)務(wù)邏輯什么都公開了。
不過就算公開對他也妹多大的影響,畢竟他會運(yùn)營 哈哈哈
而 express 的話 比較老了,不過還是比較好用的 比較有了 async awiat 后
所這么多,也是給新手一個(gè)參考,和一些新型公司在選擇框架上一個(gè)建議吧
這里這要說的市egg.js 的上傳。
首先我們在
#route.js中添加一個(gè)路由規(guī)則
router.post('/upload',controller.upload.index);
在controller
中新建upload文件
'use strict';
//node.js 文件操作對象
const fs = require('fs');
//node.js 路徑操作對象
const path = require('path');
//egg.js Controller
const Controller = require('egg').Controller;
//故名思意 異步二進(jìn)制 寫入流
const awaitWriteStream = require('await-stream-ready').write;
//管道讀入一個(gè)蟲洞。
const sendToWormhole = require('stream-wormhole');
//當(dāng)然你也可以不使用這個(gè) 哈哈 個(gè)人比較賴
//還有我們這里使用了egg-multipart
const md5 = require('md5');
class UploadController extends Controller {
async index() {
const ctx = this.ctx;
//egg-multipart 已經(jīng)幫我們處理文件二進(jìn)制對象
// node.js 和 php 的上傳唯一的不同就是 ,php 是轉(zhuǎn)移一個(gè) 臨時(shí)文件
// node.js 和 其他語言(java c#) 一樣操作文件流
const stream = await ctx.getFileStream();
//新建一個(gè)文件名
const filename = md5(stream.filename) + path
.extname(stream.filename)
.toLocaleLowerCase();
//文件生成絕對路徑
//當(dāng)然這里這樣市不行的,因?yàn)槟氵€要判斷一下是否存在文件路徑
const target = path.join(this.config.baseDir, 'app/public/uploads', filename);
//生成一個(gè)文件寫入 文件流
const writeStream = fs.createWriteStream(target);
try {
//異步把文件流 寫入
await awaitWriteStream(stream.pipe(writeStream));
} catch (err) {
//如果出現(xiàn)錯(cuò)誤,關(guān)閉管道
await sendToWormhole(stream);
throw err;
}
//文件響應(yīng)
ctx.body = {
url: '/public/uploads/' + filename
};
}
}
module.exports = UploadController;
這里使用的是 antd 的上傳組件
還有就是 這里我使用的市自己搭建的一個(gè) egg + react 框架,思路和 laravel 的差不多。
并沒有使用 egg的服務(wù)端渲染,因?yàn)檫@樣做的話,就像違背了 React + webpack 的傳統(tǒng),因?yàn)樵谑褂胣ext.js的時(shí)候 有時(shí)候的axios 的思路 你就要變成 node.js的 爬蟲思路
https://github.com/rainbowMorelhahahah/egg-react-webpack-react-router
這里市地址,可以參考下
import React, {PureComponent} from 'react';
import {withRouter} from 'react-router-dom';
import {Upload, Icon, message} from 'antd';
class UploadThumb extends PureComponent {
constructor(props) {
super(props);
this.state = {
loading: false,
imageUrl: ""
};
}
handleChange(info) {
const {imageUrl} = this.state;
if (info.file.status === 'uploading') {
this.setState({loading: true});
return;
}
if (info.file.status === 'done') {
// Get this url from response in real world.
this.getBase64(info.file.originFileObj, imageUrl => this.setState({imageUrl, loading: false}));
}
}
getBase64(img, callback) {
const reader = new FileReader();
reader.addEventListener('load', () => callback(reader.result));
reader.readAsDataURL(img);
}
beforeUpload(file) {
const isJPG = file.type === 'image/jpeg';
if (!isJPG) {
message.error('You can only upload JPG file!');
}
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isLt2M) {
message.error('Image must smaller than 2MB!');
}
return isJPG && isLt2M;
}
render() {
const uploadButton = (
<div>
<Icon
type={this.state.loading
? 'loading'
: 'plus'}/>
<div className="ant-upload-text">Upload</div>
</div>
);
return (
<Upload
name="avatar"
listType="picture-card"
className="avatar-uploader"
showUploadList={false}
action="/upload"
beforeUpload={this
.beforeUpload
.bind(this)}
onChange={this
.handleChange
.bind(this)}>
{this.state.imageUrl
? <img src={this.state.imageUrl} alt=""/>
: uploadButton}
</Upload>
);
}
}
export default withRouter(UploadThumb);