yuanjiajun commited on
Commit ·
ca63dd4
1
Parent(s): 96a676d
feat: 文件服务
Browse files- .eslintignore +3 -0
- .eslintrc.js +103 -0
- .gitignore +41 -0
- .prettierrc +5 -0
- .vscode/extensions.json +3 -0
- .vscode/settings.json +12 -0
- Dockerfile +30 -0
- nodemon.json +6 -0
- package-lock.json +0 -0
- package.json +46 -0
- src/app.ts +47 -0
- src/controllers/fileController.ts +96 -0
- src/middleware/errorMiddleware.ts +10 -0
- src/routes/fileRoutes.ts +11 -0
- tsconfig.json +20 -0
.eslintignore
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
node_modules/
|
| 2 |
+
build/
|
| 3 |
+
.eslintrc.js
|
.eslintrc.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
module.exports = {
|
| 2 |
+
root: true,
|
| 3 |
+
parser: '@typescript-eslint/parser',
|
| 4 |
+
env: {
|
| 5 |
+
node: true,
|
| 6 |
+
es6: true,
|
| 7 |
+
},
|
| 8 |
+
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'plugin:import/typescript', 'plugin:prettier/recommended'],
|
| 9 |
+
parserOptions: {
|
| 10 |
+
ecmaVersion: 2018,
|
| 11 |
+
sourceType: 'module',
|
| 12 |
+
ecmaFeatures: {
|
| 13 |
+
jsx: true,
|
| 14 |
+
},
|
| 15 |
+
project: './tsconfig.json',
|
| 16 |
+
tsconfigRootDir: __dirname,
|
| 17 |
+
},
|
| 18 |
+
plugins: ['simple-import-sort', 'filenames', 'folders', 'promise', 'eslint-comments', 'prettier', 'eslint-plugin-import'],
|
| 19 |
+
rules: {
|
| 20 |
+
'linebreak-style': ['error', 'unix'],
|
| 21 |
+
quotes: ['warn', 'single'],
|
| 22 |
+
// 文件命名规范 使用小写中划线连接
|
| 23 |
+
// 'filenames/match-regex': [2, '^[a-z]+(-[a-z0-9]+)*(.test)?$',
|
| 24 |
+
// true
|
| 25 |
+
// ], // 所有文件中划线小写
|
| 26 |
+
// 文件导出规范
|
| 27 |
+
// 'filenames/match-exported': ['error', ['kebab', 'camel', 'pascal']],
|
| 28 |
+
'filenames/no-index': 'off',
|
| 29 |
+
'import/no-dynamic-require': 'off',
|
| 30 |
+
// 开启 prettier
|
| 31 |
+
'prettier/prettier': 'error',
|
| 32 |
+
// 未使用的变量
|
| 33 |
+
'@typescript-eslint/no-unused-vars': 'error',
|
| 34 |
+
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
| 35 |
+
'@typescript-eslint/explicit-function-return-type': 'off',
|
| 36 |
+
'@typescript-eslint/comma-dangle': 'off',
|
| 37 |
+
// any 禁止使用
|
| 38 |
+
'@typescript-eslint/no-explicit-any': 'off',
|
| 39 |
+
'@typescript-eslint/no-unsafe-call': 'off',
|
| 40 |
+
'@typescript-eslint/no-unsafe-argument': 'off',
|
| 41 |
+
'@typescript-eslint/no-unsafe-return': 'off',
|
| 42 |
+
// '@typescript-eslint/no-unsafe-assignment': 'off',
|
| 43 |
+
// '@typescript-eslint/no-unsafe-declaration-merging': 'warn',
|
| 44 |
+
// '@typescript-eslint/no-unsafe-enum-comparison': 'warn',
|
| 45 |
+
// '@typescript-eslint/no-unsafe-member-access': 'warn',
|
| 46 |
+
// 定义 enmu 和 interface 命名规范
|
| 47 |
+
'@typescript-eslint/naming-convention': [
|
| 48 |
+
'error',
|
| 49 |
+
{
|
| 50 |
+
selector: 'enumMember',
|
| 51 |
+
format: ['camelCase'],
|
| 52 |
+
},
|
| 53 |
+
{
|
| 54 |
+
selector: 'enum',
|
| 55 |
+
format: ['PascalCase'],
|
| 56 |
+
// prefix: ['ENUM_'],
|
| 57 |
+
},
|
| 58 |
+
// {
|
| 59 |
+
// selector: 'interface',
|
| 60 |
+
// format: ['PascalCase'],
|
| 61 |
+
// prefix: ['I', '1'],
|
| 62 |
+
// },
|
| 63 |
+
],
|
| 64 |
+
'max-lines-per-function': 0,
|
| 65 |
+
'no-console': 'warn',
|
| 66 |
+
'simple-import-sort/exports': 'warn',
|
| 67 |
+
'import/no-cycle': 'error',
|
| 68 |
+
// 文件夹命名规范
|
| 69 |
+
// "folders/match-regex": [2, "^[a-z]+(-[a-z0-9]+)*$", "src"],
|
| 70 |
+
'promise/catch-or-return': [
|
| 71 |
+
'error',
|
| 72 |
+
{
|
| 73 |
+
allowFinally: true,
|
| 74 |
+
},
|
| 75 |
+
],
|
| 76 |
+
"promise/prefer-await-to-then": "error",
|
| 77 |
+
complexity: ['error', 20],
|
| 78 |
+
'max-depth': ['warn', 6],
|
| 79 |
+
'max-lines': [
|
| 80 |
+
'warn',
|
| 81 |
+
{
|
| 82 |
+
max: 800,
|
| 83 |
+
skipBlankLines: true,
|
| 84 |
+
skipComments: true,
|
| 85 |
+
},
|
| 86 |
+
],
|
| 87 |
+
'max-len': 'off',
|
| 88 |
+
'@typescript-eslint/ban-types': 'warn',
|
| 89 |
+
'@typescript-eslint/no-unnecessary-boolean-literal-compare': 'off',
|
| 90 |
+
'@typescript-eslint/prefer-nullish-coalescing': 'off',
|
| 91 |
+
'@typescript-eslint/no-misused-promises': [
|
| 92 |
+
'error',
|
| 93 |
+
{
|
| 94 |
+
checksVoidReturn: false,
|
| 95 |
+
},
|
| 96 |
+
],
|
| 97 |
+
'@typescript-eslint/return-await': 'off', // 这个暂时关了,autofix 可能会导致问题
|
| 98 |
+
'@typescript-eslint/no-loss-of-precision': 'off',
|
| 99 |
+
'import/no-cycle': 'warn', // 先关掉,后续解决
|
| 100 |
+
},
|
| 101 |
+
};
|
| 102 |
+
|
| 103 |
+
|
.gitignore
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
.DS_Store
|
| 2 |
+
|
| 3 |
+
.pnp
|
| 4 |
+
.pnp.js
|
| 5 |
+
.env.local
|
| 6 |
+
.env.*.local
|
| 7 |
+
.history
|
| 8 |
+
.rts*
|
| 9 |
+
*.log*
|
| 10 |
+
*.pid
|
| 11 |
+
*.pid.*
|
| 12 |
+
*.report
|
| 13 |
+
*.lcov
|
| 14 |
+
lib-cov
|
| 15 |
+
|
| 16 |
+
node_modules/
|
| 17 |
+
.npm
|
| 18 |
+
.lock-wscript
|
| 19 |
+
.yarn-integrity
|
| 20 |
+
.node_repl_history
|
| 21 |
+
.nyc_output
|
| 22 |
+
*.tsbuildinfo
|
| 23 |
+
.eslintcache
|
| 24 |
+
.sonarlint
|
| 25 |
+
|
| 26 |
+
dist/
|
| 27 |
+
coverage/
|
| 28 |
+
release/
|
| 29 |
+
output/
|
| 30 |
+
output_resource/
|
| 31 |
+
|
| 32 |
+
.vscode/**/*
|
| 33 |
+
!.vscode/settings.json
|
| 34 |
+
!.vscode/extensions.json
|
| 35 |
+
.idea/
|
| 36 |
+
|
| 37 |
+
**/*/typings/auto-generated
|
| 38 |
+
|
| 39 |
+
.changeset/pre.json
|
| 40 |
+
|
| 41 |
+
.pnpm-store/
|
.prettierrc
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"printWidth": 150,
|
| 3 |
+
"tabWidth": 2,
|
| 4 |
+
"singleQuote": true
|
| 5 |
+
}
|
.vscode/extensions.json
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"recommendations": ["dbaeumer.vscode-eslint"]
|
| 3 |
+
}
|
.vscode/settings.json
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"prettier.enable": true,
|
| 3 |
+
"eslint.enable": true,
|
| 4 |
+
"editor.codeActionsOnSave": {
|
| 5 |
+
"source.fixAll.eslint": "explicit"
|
| 6 |
+
},
|
| 7 |
+
"eslint.workingDirectories": [
|
| 8 |
+
{
|
| 9 |
+
"mode": "auto"
|
| 10 |
+
}
|
| 11 |
+
]
|
| 12 |
+
}
|
Dockerfile
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 使用官方 Node 镜像作为基础镜像
|
| 2 |
+
FROM node:14
|
| 3 |
+
|
| 4 |
+
VOLUME /app/static
|
| 5 |
+
|
| 6 |
+
# 设置工作目录
|
| 7 |
+
WORKDIR /usr/src/app
|
| 8 |
+
|
| 9 |
+
# 创建上传文件夹
|
| 10 |
+
RUN mkdir -p /usr/src/app/uploads && chown -R node:node /usr/src/app/uploads
|
| 11 |
+
|
| 12 |
+
# 复制 package.json 和 package-lock.json
|
| 13 |
+
COPY package*.json ./
|
| 14 |
+
|
| 15 |
+
# 复制项目文件到工作目录
|
| 16 |
+
COPY . .
|
| 17 |
+
|
| 18 |
+
# 安装项目依赖
|
| 19 |
+
RUN npm install
|
| 20 |
+
|
| 21 |
+
RUN npm run build && [ $? -eq 0 ]
|
| 22 |
+
|
| 23 |
+
# 暴露应用运行端口
|
| 24 |
+
EXPOSE 3000
|
| 25 |
+
|
| 26 |
+
# 定义环境变量
|
| 27 |
+
ENV PORT=3000
|
| 28 |
+
|
| 29 |
+
# 启动应用
|
| 30 |
+
CMD ["npm", "start"]
|
nodemon.json
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"watch": ["src"],
|
| 3 |
+
"ext": "ts",
|
| 4 |
+
"ignore": ["src/**/*.spec.ts"],
|
| 5 |
+
"exec": "ts-node -r tsconfig-paths/register ./src/app.ts"
|
| 6 |
+
}
|
package-lock.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"name": "stt",
|
| 3 |
+
"version": "1.0.0",
|
| 4 |
+
"description": "--- title: Stt emoji: 🦀 colorFrom: purple colorTo: pink sdk: docker pinned: false license: mit ---",
|
| 5 |
+
"main": ".eslintrc.js",
|
| 6 |
+
"scripts": {
|
| 7 |
+
"dev": "nodemon",
|
| 8 |
+
"build": "tsc && tsc-alias",
|
| 9 |
+
"start": "node ./dist/app.js",
|
| 10 |
+
"lint": "eslint --ext .ts src --fix"
|
| 11 |
+
},
|
| 12 |
+
"repository": {
|
| 13 |
+
"type": "git",
|
| 14 |
+
"url": "https://huggingface.co/spaces/Joey7938/stt"
|
| 15 |
+
},
|
| 16 |
+
"author": "",
|
| 17 |
+
"license": "ISC",
|
| 18 |
+
"dependencies": {
|
| 19 |
+
"@types/koa": "^2.15.0",
|
| 20 |
+
"@types/koa-static": "^4.0.4",
|
| 21 |
+
"eslint-plugin-prettier": "^5.2.1",
|
| 22 |
+
"koa": "^2.15.3",
|
| 23 |
+
"koa-body": "^6.0.1",
|
| 24 |
+
"koa-bodyparser": "^4.4.1",
|
| 25 |
+
"koa-mount": "^4.0.0",
|
| 26 |
+
"koa-router": "^13.0.1",
|
| 27 |
+
"koa-static": "^5.0.0",
|
| 28 |
+
"nodemon": "^3.1.7"
|
| 29 |
+
},
|
| 30 |
+
"devDependencies": {
|
| 31 |
+
"@eslint/js": "^9.14.0",
|
| 32 |
+
"@types/html-docx-js": "^0.3.4",
|
| 33 |
+
"@types/koa-bodyparser": "^4.3.12",
|
| 34 |
+
"@types/koa-mount": "^4.0.5",
|
| 35 |
+
"@types/koa-router": "^7.4.8",
|
| 36 |
+
"@types/node": "^17.0.45",
|
| 37 |
+
"@typescript-eslint/parser": "^5.62.0",
|
| 38 |
+
"eslint": "^8.57.1",
|
| 39 |
+
"eslint-plugin-import": "^2.31.0",
|
| 40 |
+
"prettier": "^3.3.3",
|
| 41 |
+
"ts-node": "^10.9.2",
|
| 42 |
+
"tsconfig-paths": "^4.2.0",
|
| 43 |
+
"typescript": "^5.6.3",
|
| 44 |
+
"typescript-eslint": "^7.18.0"
|
| 45 |
+
}
|
| 46 |
+
}
|
src/app.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import Koa from 'koa';
|
| 2 |
+
import bodyParser from 'koa-body';
|
| 3 |
+
import mount from 'koa-mount';
|
| 4 |
+
import staticMiddleware from 'koa-static';
|
| 5 |
+
import fileRoutes from './routes/fileRoutes';
|
| 6 |
+
import { errorMiddleware } from './middleware/errorMiddleware';
|
| 7 |
+
import bodyparser from 'koa-bodyparser';
|
| 8 |
+
import path from 'path';
|
| 9 |
+
|
| 10 |
+
const app = new Koa();
|
| 11 |
+
|
| 12 |
+
// 自定义中间件解析二进制数据
|
| 13 |
+
app.use(async (ctx, next) => {
|
| 14 |
+
if (ctx.request.header['content-type'] === 'application/octet-stream') {
|
| 15 |
+
const chunks = [];
|
| 16 |
+
for await (const chunk of ctx.req) {
|
| 17 |
+
chunks.push(chunk);
|
| 18 |
+
}
|
| 19 |
+
ctx.request.body = Buffer.concat(chunks);
|
| 20 |
+
}
|
| 21 |
+
await next();
|
| 22 |
+
});
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
// 配置 bodyparser
|
| 26 |
+
app.use(bodyparser());
|
| 27 |
+
|
| 28 |
+
// 日志中间件
|
| 29 |
+
app.use(async (ctx, next) => {
|
| 30 |
+
const start = Date.now();
|
| 31 |
+
await next();
|
| 32 |
+
const ms = Date.now() - start;
|
| 33 |
+
console.log(`${ctx.method} ${ctx.url} - ${ctx.status} ${ms}ms`);
|
| 34 |
+
});
|
| 35 |
+
|
| 36 |
+
app.use(errorMiddleware);
|
| 37 |
+
app.use(bodyParser({ multipart: true }));
|
| 38 |
+
app.use(mount('/uploads', staticMiddleware(path.join(__dirname, '../../uploads'))));
|
| 39 |
+
app.use(fileRoutes.routes());
|
| 40 |
+
app.use(fileRoutes.allowedMethods());
|
| 41 |
+
|
| 42 |
+
// const PORT = process.env.PORT || 3000;
|
| 43 |
+
const PORT = process.env.PORT || 3001;
|
| 44 |
+
|
| 45 |
+
app.listen(PORT, () => {
|
| 46 |
+
console.log(`Server is running on port ${PORT}`);
|
| 47 |
+
});
|
src/controllers/fileController.ts
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import * as fs from 'fs';
|
| 2 |
+
import * as path from 'path';
|
| 3 |
+
import { Context } from 'koa';
|
| 4 |
+
|
| 5 |
+
const UPLOAD_DIR = path.join(__dirname, '../../uploads');
|
| 6 |
+
|
| 7 |
+
if (!fs.existsSync(UPLOAD_DIR)) {
|
| 8 |
+
fs.mkdirSync(UPLOAD_DIR, { recursive: true });
|
| 9 |
+
}
|
| 10 |
+
|
| 11 |
+
export const getFileNameList = async (ctx: Context) => {
|
| 12 |
+
try {
|
| 13 |
+
const files = fs.readdirSync(UPLOAD_DIR);
|
| 14 |
+
ctx.body = { files };
|
| 15 |
+
} catch (error: any) {
|
| 16 |
+
ctx.status = 500;
|
| 17 |
+
ctx.body = { error: error.message };
|
| 18 |
+
}
|
| 19 |
+
};
|
| 20 |
+
|
| 21 |
+
export const uploadFile = async (ctx: Context) => {
|
| 22 |
+
try {
|
| 23 |
+
if (!ctx.request.body || !ctx.request.header['content-disposition']) {
|
| 24 |
+
ctx.status = 400;
|
| 25 |
+
ctx.body = { error: 'No file or file name uploaded' };
|
| 26 |
+
return;
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
const fileBuffer = ctx.request.body;
|
| 30 |
+
const contentDisposition = ctx.request.header['content-disposition'];
|
| 31 |
+
const fileNameMatch = contentDisposition.match(/filename=(.+)/);
|
| 32 |
+
|
| 33 |
+
if (!fileNameMatch) {
|
| 34 |
+
ctx.status = 400;
|
| 35 |
+
ctx.body = { error: 'File name not found in Content-Disposition header' };
|
| 36 |
+
return;
|
| 37 |
+
}
|
| 38 |
+
|
| 39 |
+
const fileName = fileNameMatch[1];
|
| 40 |
+
const targetPath = path.join(UPLOAD_DIR, fileName);
|
| 41 |
+
|
| 42 |
+
console.log( fileBuffer);
|
| 43 |
+
fs.writeFileSync(targetPath, fileBuffer);
|
| 44 |
+
ctx.body = { message: 'File uploaded successfully' };
|
| 45 |
+
} catch (error: any) {
|
| 46 |
+
ctx.status = 500;
|
| 47 |
+
ctx.body = { error: error.message };
|
| 48 |
+
}
|
| 49 |
+
};
|
| 50 |
+
|
| 51 |
+
export const getFile = async (ctx: Context) => {
|
| 52 |
+
try {
|
| 53 |
+
const fileName = ctx.params.fileName;
|
| 54 |
+
const filePath = path.join(UPLOAD_DIR, fileName);
|
| 55 |
+
|
| 56 |
+
if (!fs.existsSync(filePath)) {
|
| 57 |
+
ctx.status = 404;
|
| 58 |
+
ctx.body = { error: 'File not found' };
|
| 59 |
+
return;
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
ctx.attachment(fileName);
|
| 63 |
+
ctx.body = fs.createReadStream(filePath);
|
| 64 |
+
} catch (error: any) {
|
| 65 |
+
ctx.status = 500;
|
| 66 |
+
ctx.body = { error: error.message };
|
| 67 |
+
}
|
| 68 |
+
};
|
| 69 |
+
|
| 70 |
+
export const deleteFile = async (ctx: Context) => {
|
| 71 |
+
try {
|
| 72 |
+
console.log('1231321');
|
| 73 |
+
const { fileName } = ctx.request.body;
|
| 74 |
+
|
| 75 |
+
if (!fileName) {
|
| 76 |
+
ctx.status = 400;
|
| 77 |
+
ctx.body = { error: 'File name is required' };
|
| 78 |
+
return;
|
| 79 |
+
}
|
| 80 |
+
|
| 81 |
+
const filePath = path.join(UPLOAD_DIR, fileName);
|
| 82 |
+
console.log('filePathdsadsadsa');
|
| 83 |
+
console.log(filePath);
|
| 84 |
+
if (!fs.existsSync(filePath)) {
|
| 85 |
+
ctx.status = 404;
|
| 86 |
+
ctx.body = { error: 'File not found' };
|
| 87 |
+
return;
|
| 88 |
+
}
|
| 89 |
+
|
| 90 |
+
fs.unlinkSync(filePath);
|
| 91 |
+
ctx.body = { message: 'File deleted successfully' };
|
| 92 |
+
} catch (error: any) {
|
| 93 |
+
ctx.status = 500;
|
| 94 |
+
ctx.body = { error: error.message };
|
| 95 |
+
}
|
| 96 |
+
};
|
src/middleware/errorMiddleware.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { Middleware } from 'koa';
|
| 2 |
+
|
| 3 |
+
export const errorMiddleware: Middleware = async (ctx, next) => {
|
| 4 |
+
try {
|
| 5 |
+
await next();
|
| 6 |
+
} catch (error) {
|
| 7 |
+
ctx.status = 500;
|
| 8 |
+
ctx.body = { error: error };
|
| 9 |
+
}
|
| 10 |
+
};
|
src/routes/fileRoutes.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import Router from 'koa-router';
|
| 2 |
+
import { getFileNameList, uploadFile, getFile, deleteFile } from '../controllers/fileController';
|
| 3 |
+
|
| 4 |
+
const router = new Router();
|
| 5 |
+
|
| 6 |
+
router.get('/file/getFileNameList', getFileNameList);
|
| 7 |
+
router.post('/file/uploadFile', uploadFile);
|
| 8 |
+
router.get('/file/getFile/:fileName', getFile);
|
| 9 |
+
router.post('/file/deleteFile', deleteFile);
|
| 10 |
+
|
| 11 |
+
export default router;
|
tsconfig.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"compilerOptions": {
|
| 3 |
+
"target": "es6",
|
| 4 |
+
"module": "commonjs",
|
| 5 |
+
"outDir": "./dist",
|
| 6 |
+
"rootDir": "./src",
|
| 7 |
+
"moduleResolution": "node",
|
| 8 |
+
"strict": true,
|
| 9 |
+
"skipLibCheck": true,
|
| 10 |
+
"forceConsistentCasingInFileNames": true,
|
| 11 |
+
"esModuleInterop": true,
|
| 12 |
+
"allowSyntheticDefaultImports": true,
|
| 13 |
+
"baseUrl": ".", // 对应文件系统中的根路径
|
| 14 |
+
"paths": {
|
| 15 |
+
"@/*": ["src/*"] // 将 @/ 映射到 src/ 目录
|
| 16 |
+
},
|
| 17 |
+
},
|
| 18 |
+
"include": ["src"],
|
| 19 |
+
"exclude": ["node_modules", "dist"]
|
| 20 |
+
}
|