📜 Midway 使用 MinIo
阿里云 FC 环境,文件需要小于 6M。
先使用 Midway 创建一个项目
npm init midway
1
选择
⊙ Serverless Application Migration
egg-layer-midway - A egg-layer boilerplate for Midway v2 application migration
1
2
2
然后安装所需要的依赖
npm i minio stream-wormhole
1
开启 文件上传
// src/config/config.default.ts
config.multipart = {
mode: "stream", // file | stream | buffer
};
config.multipart = {
// 表单 Field 文件名长度限制
fieldNameSize: 100,
// 表单 Field 内容大小
fieldSize: "100kb",
// 表单 Field 最大个数
fields: 10,
// 单个文件大小
fileSize: "10mb", // 如果要上传大文件,就需要修改这里
// 允许上传的最大文件数
files: 10,
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
这里直接使用 steam 模式,其他两种模式看 参考 中的 Egg 文献。
如果是部署在 阿里云 Serverless ,上传大文件你会遇见:
{
"ErrorCode": "EntityTooLarge",
"ErrorMessage": "payload size exceeds maximum allowed size (6291456 bytes)"
}
1
2
3
4
2
3
4
Controller
import {
App,
Controller,
Get,
Inject,
Post,
Provide,
} from "@midwayjs/decorator";
import { Application, Context } from "egg";
import { FileStream } from "../../typings/app";
import * as sendToWormhole from "stream-wormhole";
import { MinIoService } from "../service/minio";
@Provide()
@Controller("/")
export class HomeController {
@App()
app: Application;
@Inject()
ctx: Context;
@Inject()
service: MinIoService;
@Get("/")
async home() {
const html = `
<form action="/upload" method="POST" enctype="multipart/form-data">
bucket : <input name="bucket" /> <br>
file name : <input name="fileNanme" /> <br>
<input type="file" name="file"> <br>
<button type="submit">上传</button>
</form>
`;
return html;
}
@Post("/upload")
async upload() {
const stream: FileStream = await this.ctx.getFileStream();
try {
const { bucket, fileNanme } = stream?.fields;
// console.log('body > ',stream.fields);
// console.log('file > ',stream.filename)
const res = await this.service.saveFile({
bucketName: bucket || "midway",
objectName: `test/${fileNanme || stream.filename}`,
stream: stream as any,
});
return { flag: true, code: 200, msg: "上传成功", info: res };
} catch (error) {
// 必须将上传的文件流消费掉,要不然浏览器响应会卡死
await sendToWormhole(stream);
return { flag: false, code: 500, msg: error.message };
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
通过 await this.ctx.getFileStream(); 获取流,是一个 FileStream(egg 提供) ,有文件的详细信息。
FileStream 的 fields 还提供 表单其他字段。
不得不说,Egg 是真的强大。
Service
import { Provide } from "@midwayjs/decorator";
import * as minio from "minio";
import { Readable } from "stream";
@Provide()
export class MinIoService {
private config = {
endPoint: "www.you.domain.com",
port: 443, // http 80 , https 443
useSSL: true,
accessKey: "x x x x x x x", // 用户ID
secretKey: "yyyyy/zzzzzzzzzz", // pwd
};
private minio: minio.Client;
constructor() {
this.minio = new minio.Client(this.config);
}
async saveFile(q: {
bucketName: string;
objectName: string;
stream: Readable | Buffer | string;
size?: number;
contentType?: any;
}) {
const { bucketName, objectName, stream, size, contentType } = q;
return new Promise((ok, err) => {
this.minio.putObject(
bucketName,
objectName,
stream,
size,
contentType,
(e, tag) => {
if (e) return err(e);
ok(tag);
}
);
});
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45