Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Provide file mode to handle multipart request #19

Merged
merged 3 commits into from
Sep 29, 2018
Merged

Conversation

fengmk2
Copy link
Member

@fengmk2 fengmk2 commented Sep 28, 2018

see RFC to get detail: eggjs/egg#3052

closes eggjs/egg#3052

package.json Show resolved Hide resolved
@codecov
Copy link

codecov bot commented Sep 28, 2018

Codecov Report

Merging #19 into master will decrease coverage by 1.89%.
The diff coverage is 97.08%.

Impacted file tree graph

@@           Coverage Diff            @@
##           master     #19     +/-   ##
========================================
- Coverage     100%   98.1%   -1.9%     
========================================
  Files           3       5      +2     
  Lines          56     158    +102     
========================================
+ Hits           56     155     +99     
- Misses          0       3      +3
Impacted Files Coverage Δ
config/config.default.js 100% <100%> (ø) ⬆️
app.js 100% <100%> (ø) ⬆️
app/extend/context.js 100% <100%> (ø) ⬆️
app/schedule/clean_tmpdir.js 93.33% <93.33%> (ø)
app/middleware/multipart.js 98.24% <98.24%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 0b4e118...a9c9507. Read the comment docs.

@fengmk2
Copy link
Member Author

fengmk2 commented Sep 28, 2018

示例 eggjs/examples#86

@fengmk2 fengmk2 changed the title [WIP] easy feat: Provide file mode to handle multipart request Sep 28, 2018
const moment = require('moment');

module.exports = app => {
return class CleanTmpdir extends (app.Subscription || app.BaseContextClass) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


options.mode = options.mode || 'stream';
if (![ 'stream', 'file' ].includes(options.mode)) {
throw new TypeError(`Expect mode to be 'stream' or 'file', but got '${options.mode}'`);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里没有覆盖。

return await limit(requestFiles, 'Request_fieldSize_limit', 'Reach fieldSize limit');
}
if (fieldnameTruncated) {
return await limit(requestFiles, 'Request_fieldNameSize_limit', 'Reach fieldNameSize limit');
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

busboy 目前不支持,所以无法覆盖。

fengmk2 added a commit to eggjs/examples that referenced this pull request Sep 28, 2018

## `file` mode: the easy way

If you don't know the [Node.js Stream](https://nodejs.org/dist/latest-v10.x/docs/api/stream.html) work, maybe you should use the `file` mode to get started.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the quickstart for Node newcomer who don't familiar with Node.js Stream .

You should not use this feature at big project, using Stream could avoid memory issues.

cc @Maledong help for the english

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should not use this feature at big project, using Stream could avoid memory issues.

未必的,使用文件也不会出问题。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

速度会有影响吧,一个是边接收边送过去 oss,一个是先存到本地,再丢 oss

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

在语雀的真实用途中,如果真的要对文件进行处理,保存到磁盘会更快。传送到 oss 的速度还取决于用户到服务器的速度。其实两者差别不大,除非你的服务器与 oss 很慢。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

也是,学习了

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

传送到 oss 的速度还取决于用户到服务器的速度。

这个其实 nginx 也会做,解决用户到服务器的问题

};
```

## `stream` mode: the hard way
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the hard and recommended way

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

不推荐。。。我们也未必能写好。你看看中间件里面的异常处理代码。

app/middleware/multipart.js Show resolved Hide resolved
app/middleware/multipart.js Show resolved Hide resolved
app/middleware/multipart.js Show resolved Hide resolved
app/schedule/clean_tmpdir.js Show resolved Hide resolved
package.json Outdated
"lint": "eslint .",
"test": "npm run lint -- --fix && npm run test-local",
"lint": "eslint . --fix",
"test": "npm run lint && npm run test-local",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should change to npm run lint -- --fix

package.json Outdated
},
"description": "multipart plugin for egg",
"main": "index.js",
"scripts": {
"autod": "autod",
"lint": "eslint .",
"test": "npm run lint -- --fix && npm run test-local",
"lint": "eslint . --fix",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will make ci skip lint check

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

windows 下没有 --fix 会导致换行符错误。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

git 配置问题? 其他项目都不会在 ci 用 --fix 的,win 的单测都没问题

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

应该是 git 配置问题,加了 fix 等于没测

@@ -13,6 +16,7 @@
"test-local": "egg-bin test",
"cov": "egg-bin cov",
"ci": "egg-bin pkgfiles && npm run lint && npm run cov",
"ci-windows": "egg-bin pkgfiles && npm run lint -- --fix && npm run cov",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

加个单独的配置给 azure-pipelines

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--fix 可以去掉

@fengmk2 fengmk2 merged commit 75c0733 into master Sep 29, 2018
@fengmk2 fengmk2 deleted the easy-mode branch September 29, 2018 06:46
@atian25
Copy link
Member

atian25 commented Sep 29, 2018

文档也要对应更新下

fengmk2 added a commit to eggjs/examples that referenced this pull request Sep 29, 2018
fengmk2 added a commit to eggjs/examples that referenced this pull request Sep 29, 2018

## License

[MIT](LICENSE)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里导致 egg 文档编译出错了,要写全链

https://github.com/eggjs/egg-multipart/blob/master/LICENSE

cc @Maledong

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

其实不是编译错,是测试错

@popomore
Copy link
Member

覆盖率下降了

- `ctx.request.body`: Get all the multipart fields and values, except `file`.
- `ctx.request.files`: Contains all `file` from the multipart request, it's an Array object.

**WARNING: you should remove the temporary upload file after you use it**
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

需要自己删?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

需要

result = await ctx.oss.put(name, file.filepath);
} finally {
// need to remove the tmp file
await fs.unlink(file.filepath);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

可以在这次请求完成后自动删除?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

不行的,没法判断怎样才算请求完,开发者可以后台处理

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

后台处理就没办法了

throw err;
}

if (!part) break;
Copy link
Member

@popomore popomore Sep 30, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里是指空文件吗? 看来是没有字段,那是不是直接 while 会比较好。

if (!storedir) {
// ${tmpdir}/YYYY/MM/DD/HH
storedir = path.join(options.tmpdir, moment().format('YYYY/MM/DD/HH'));
const exists = await fs.exists(storedir);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

每个请求都会走下 io、

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

只有有 file 才会走

}
const filepath = path.join(storedir, uuid.v4() + path.extname(meta.filename));
const target = fs.createWriteStream(filepath);
await pump(part, target);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个报错不 clean 下?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里可以优化

} catch (err) {
ctx.coreLogger.error('[egg-multipart:CleanTmpdir:error] remove tmpdir: %j error: %s',
dir, err);
ctx.coreLogger.error(err);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

直接改 err.message?

fengmk2 pushed a commit to eggjs/egg that referenced this pull request Sep 30, 2018
Due to eggjs/egg-multipart#19, we have to
add this new feature into Egg's main doc in controller.md to notify
clients.
popomore pushed a commit to eggjs/egg that referenced this pull request Sep 30, 2018
docs (Controller.md): Add new feat description (#3066)

Due to eggjs/egg-multipart#19, we have to
add this new feature into Egg's main doc in controller.md to notify
clients.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[RFC] Provide an easy way to handle file upload
3 participants