Skip to content

Commit 493a338

Browse files
committed
增加文件上传服务
1 parent d263606 commit 493a338

File tree

5 files changed

+174
-315
lines changed

5 files changed

+174
-315
lines changed

README.md

+31-3
Original file line numberDiff line numberDiff line change
@@ -91,15 +91,40 @@ module.exports = {
9191
使用
9292
```javascript
9393
// webpack.config.js
94+
const path = require('path');
9495
const KsMock = require("ks-mock");
9596
module.exports = {
9697
...
9798
plugins: [
9899
new KsMock({
99-
mockData: {},
100+
// // 静态文件目录
101+
// static: path.join(__dirname, 'upload'),
102+
103+
// 上传文件/写入文件前的钩子
104+
// beforeUpload(req, file, done) {
105+
// // 参数: 错误对象, 要存储的目录
106+
// done(null, '')
107+
// },
108+
// beforeWrite(req, file, done) {
109+
// // 参数: 错误对象, 要存储的文件名
110+
// done(null, '')
111+
// },
112+
113+
mockData: {},
100114
headConfig: null,
101115
crossDomain: true,
102-
port: 3030
116+
port: 3030,
117+
118+
// // 配置路由重写规则
119+
// rules: {
120+
// '/api/*': '/api?name=$1'
121+
// },
122+
123+
// // 配置https证书
124+
// https: {
125+
// key: '',
126+
// cert: ''
127+
// }
103128
})
104129
...
105130
]
@@ -124,14 +149,17 @@ module.exports = {
124149
|- package.json
125150
|- rollup.config.js <font color="green">rollup配置</font>
126151

127-
152+
string | ((jsonServer: Object, server: Object) => void)
128153
### 配置项
129154
|属性|类型|默认值|说明|
130155
|--|--|--|--|
131156
| mockData | object | {} | 模拟属性相关的配置 |
132157
| headConfig | object | null | 服务器请求头设置 |
133158
| crossDomain | boolean | true | 是否允许跨域 当 headConfig 不为空时, 忽略该项 |
134159
| port | number | 3030 | 端口号 |
160+
| static | object/function | __dirname + '/public' | 静态文件目录 |
161+
| beforeUpload | function | undefined | 上传文件前的钩子 |
162+
| beforeWrite | function | undefined | 写入文件前的钩子 |
135163
| https | object/undefined | undefined | https配置 |
136164
| rules | object | - | 路由重写规则, 参考 [json-server rewriter](https://github.com/typicode/json-server#rewriter-example) |
137165
| loginUrl | string | - | 登录地址, 如果配置了loginUrl, 那么除登录和public属性为true的接口外, 其它接口必须在登录之后才可以正常执行 |

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ks-mock",
3-
"version": "1.3.4",
3+
"version": "1.3.5",
44
"description": "mock server 模拟后端API接口",
55
"main": "index.js",
66
"scripts": {
@@ -40,6 +40,7 @@
4040
"@types/mocha": "^5.2.6",
4141
"@types/node": "^12.0.0",
4242
"jest": "^24.9.0",
43+
"multer": "^1.4.4",
4344
"rollup-plugin-typescript": "^1.0.1",
4445
"tslib": "*",
4546
"typedoc": "^0.14.2",

src/server.ts

+101-60
Original file line numberDiff line numberDiff line change
@@ -4,69 +4,51 @@ import auth from './auth';
44
import config from './config';
55
import rules from './rules';
66
import * as https from 'https';
7-
import { Http, noop, getInfo, formatResult, mockResult, authHandler, errorHandler, relayHandler, methodHandler } from './utils'
7+
import { Http, noop, once, getInfo, formatResult, mockResult, authHandler, errorHandler, relayHandler, methodHandler } from './utils'
88
import * as fs from 'fs';
99
import { mock } from '../';
1010
const server = jsonServer.create()
11-
// 路径从根目录开始?
12-
const router = jsonServer.router(path.resolve(process.cwd(), 'db.json'))
1311

14-
const createServer = (option: mock.anyObject, callback?: Function) => {
15-
let config = option.https
16-
config = /^(boolean|number)$/.test(typeof config) ? config && {} : config
17-
let currentServer
18-
if (config instanceof Object) {
19-
if (typeof config.static === 'function') {
20-
config.static(jsonServer, server)
21-
} else {
22-
const middlewares = jsonServer.defaults({
23-
static: typeof config.static === 'string' ? config.static : path.resolve(process.cwd(), './public')
24-
})
25-
server.use(middlewares)
26-
}
27-
if (typeof config.key !== 'string' || typeof config.cert !== 'string' || config.key.length + config.cert.length === 0) {
28-
config.key = fs.readFileSync(path.join(__dirname, 'ssl/key.pem'))
29-
config.cert = fs.readFileSync(path.join(__dirname, 'ssl/cert.pem'))
30-
console.log("正在使用默认的证书配置")
31-
}
32-
currentServer = https.createServer(config, server).listen(option.port, function () {
33-
console.log()
34-
console.log(`已启动json-server服务器 https://localhost:${option.port}`)
35-
console.log()
36-
typeof callback == 'function' && callback();
37-
})
12+
// 静态文件服务
13+
const useStaticServer = (option) => {
14+
if (typeof option.static === 'function') {
15+
option.static(jsonServer, server)
3816
} else {
39-
currentServer = server.listen(option.port, () => {
40-
console.log()
41-
console.log(`已启动json-server服务器 http://localhost:${option.port}`)
42-
console.log()
43-
typeof callback == 'function' && callback();
17+
const middlewares = jsonServer.defaults({
18+
static: typeof option.static === 'string' ? option.static : path.resolve(__dirname, './public')
4419
})
20+
server.use(middlewares)
4521
}
46-
currentServer.on('error', (...rest) => {
47-
option.port++
48-
createServer(option, callback)
22+
}
23+
24+
// 上传文件服务
25+
const useUploadServer = (option) => {
26+
const multer = require('multer')
27+
const storage = multer.diskStorage({
28+
destination: function (req, file, cb) {
29+
const done = once(cb)
30+
if (noop(option.beforeUpload).call(option, req, file, done) !== false) {
31+
done(null, option.uploadPath || path.join(__dirname, '/uploads'))
32+
}
33+
},
34+
filename: function (req, file, cb) {
35+
const done = once(cb)
36+
if (noop(option.beforeWrite).call(option, req, file, done) !== false) {
37+
done(null, file.originalname)
38+
}
39+
}
4940
})
41+
const upload = multer({ storage })
42+
server.use(upload.any())
5043
}
5144

52-
/**
53-
* 启动mock服务
54-
* @func
55-
* @param {object} option mock 服务配置
56-
* @param {mockData} option.mockData - mock数据json(支持 mockjs 中的写法)
57-
* @param {headoption=} option.headoption - 服务端请求头信息配置
58-
* @param {boolean=} option.crossDomain - 是否跨域 (便于在不设置请求头时, 快速配置跨域)
59-
* @param {number=} port - 服务器端口
60-
*/
61-
const Server = (option: mock.anyObject, callback?: Function) => {
62-
option = Object.assign({
63-
port: 3030,
64-
crossDomain: true,
65-
headoption: null,
66-
mockData: {},
67-
bounded: !!option.loginUrl
68-
}, option)
45+
const useRouter = (option) => {
46+
47+
// 路径从根目录开始?
48+
const router = jsonServer.router(path.resolve(process.cwd(), 'db.json'))
49+
6950
let mockData = option.mockData
51+
7052
// To handle POST, PUT and PATCH you need to use a body-parser
7153
// You can use the one used by JSON Server
7254
server.use(jsonServer.bodyParser)
@@ -86,8 +68,9 @@ const Server = (option: mock.anyObject, callback?: Function) => {
8668
method,
8769
urlKey,
8870
params,
89-
headConfig
90-
} = getInfo(req, option, config.crossDomain)
71+
headConfig,
72+
extra
73+
} = getInfo(req, option, config.crossDomain, res)
9174
let result = {}
9275
// 是否需要将接口的处理逻辑交由json-server
9376
let transfer = method === 'post' && router.db.__wrapped__.hasOwnProperty(urlKey)
@@ -99,7 +82,8 @@ const Server = (option: mock.anyObject, callback?: Function) => {
9982
data,
10083
method,
10184
params,
102-
result
85+
result,
86+
extra
10387
})
10488
const allOption = {
10589
req,
@@ -112,7 +96,8 @@ const Server = (option: mock.anyObject, callback?: Function) => {
11296
option,
11397
headConfig,
11498
result,
115-
transfer
99+
transfer,
100+
extra
116101
}
117102
// 2. 处理鉴权
118103
if (authHandler(allOption) === false) { return }
@@ -146,7 +131,8 @@ const Server = (option: mock.anyObject, callback?: Function) => {
146131
method,
147132
urlKey,
148133
params,
149-
} = getInfo(req, option, config.crossDomain)
134+
extra
135+
} = getInfo(req, option, config.crossDomain, res)
150136
mockData = mockData || {}
151137
let body = {
152138
code: 201,
@@ -165,16 +151,71 @@ const Server = (option: mock.anyObject, callback?: Function) => {
165151
method,
166152
params,
167153
JSON.parse(JSON.stringify(current[method] instanceof Object ? current[method] : {})),
168-
{
154+
Object.assign({}, extra, {
169155
url,
170156
body: JSON.parse(JSON.stringify(body))
171-
}
157+
})
172158
) || body)
173159
}
174160
// post成功后, 对其返回数据进行包装
175161
res.status(200).jsonp(body)
176162
}
163+
177164
server.use(router)
178-
createServer(option, callback)
165+
}
166+
167+
const createServer = (option: mock.anyObject, callback?: Function) => {
168+
let config = option.https
169+
config = /^(boolean|number)$/.test(typeof config) ? config && {} : config
170+
let currentServer
171+
useStaticServer(option)
172+
useUploadServer(option)
173+
useRouter(option)
174+
175+
if (config instanceof Object) {
176+
if (typeof config.key !== 'string' || typeof config.cert !== 'string' || config.key.length + config.cert.length === 0) {
177+
config.key = fs.readFileSync(path.join(__dirname, 'ssl/key.pem'))
178+
config.cert = fs.readFileSync(path.join(__dirname, 'ssl/cert.pem'))
179+
console.log("正在使用默认的证书配置")
180+
}
181+
currentServer = https.createServer(config, server).listen(option.port, function () {
182+
option.serverUrl = `https://localhost:${option.port}`
183+
console.log()
184+
console.log(`已启动json-server服务器 ${option.serverUrl}`)
185+
console.log()
186+
typeof callback == 'function' && callback();
187+
})
188+
} else {
189+
currentServer = server.listen(option.port, () => {
190+
option.serverUrl = `http://localhost:${option.port}`
191+
console.log()
192+
console.log(`已启动json-server服务器 ${option.serverUrl}`)
193+
console.log()
194+
typeof callback == 'function' && callback();
195+
})
196+
}
197+
currentServer.on('error', (...rest) => {
198+
option.port++
199+
createServer(option, callback)
200+
})
201+
}
202+
203+
/**
204+
* 启动mock服务
205+
* @func
206+
* @param {object} option mock 服务配置
207+
* @param {mockData} option.mockData - mock数据json(支持 mockjs 中的写法)
208+
* @param {headoption=} option.headoption - 服务端请求头信息配置
209+
* @param {boolean=} option.crossDomain - 是否跨域 (便于在不设置请求头时, 快速配置跨域)
210+
* @param {number=} port - 服务器端口
211+
*/
212+
const Server = (option: mock.anyObject, callback?: Function) => {
213+
createServer(Object.assign({
214+
port: 3030,
215+
crossDomain: true,
216+
headoption: null,
217+
mockData: {},
218+
bounded: !!option.loginUrl
219+
}, option), callback)
179220
}
180221
export default Server

0 commit comments

Comments
 (0)