mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-17 09:36:08 +08:00
framework: auto cleanup uploaded files (#818)
This commit is contained in:
10 files changed
+40
-24
No files matched your search
@@ -86,6 +86,7 @@ export type KoaContext = Koa.Context & {
|
||||
handler: any;
|
||||
request: Koa.Request & { body: any, files: Files };
|
||||
session: Record<string, any>;
|
||||
holdFiles: (string | File)[];
|
||||
};
|
||||
|
||||
const logger = new Logger('server');
|
||||
@@ -199,6 +200,10 @@ export class Handler extends HandlerCommon {
|
||||
if (name) this.response.disposition = `attachment; filename="${encodeRFC5987ValueChars(name)}"`;
|
||||
}
|
||||
|
||||
holdFile(name: string | File) {
|
||||
this.context.holdFiles.push(name);
|
||||
}
|
||||
|
||||
async init() {
|
||||
if (this.request.method === 'post' && this.request.headers.referer && !this.context.cors && !this.allowCors) {
|
||||
try {
|
||||
@@ -394,6 +399,20 @@ ${c.response.status} ${endTime - startTime}ms ${c.response.length}`);
|
||||
keepExtensions: true,
|
||||
},
|
||||
}));
|
||||
this.server.use(async (c, next) => {
|
||||
c.holdFiles = [];
|
||||
try {
|
||||
await next();
|
||||
} finally {
|
||||
if (Object.keys(c.request.files || {}).length) {
|
||||
for (const k in c.request.files) {
|
||||
if (c.holdFiles.includes(k)) continue;
|
||||
const files = Array.isArray(c.request.files[k]) ? c.request.files[k] : [c.request.files[k]];
|
||||
for (const f of files) if (!c.holdFiles.includes(f as any)) fs.rmSync(f.filepath);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
this.ctx.on('dispose', () => {
|
||||
fs.emptyDirSync(uploadDir);
|
||||
});
|
||||
|
||||
@@ -82,12 +82,12 @@ class FpsProblemImportHandler extends Handler {
|
||||
}
|
||||
|
||||
async post({ domainId }) {
|
||||
if (!this.request.files.file) throw new ValidationError('file');
|
||||
const file = this.request.files.file;
|
||||
if (!file) throw new ValidationError('file');
|
||||
const tasks = [];
|
||||
try {
|
||||
const file = await fs.stat(this.request.files.file.filepath);
|
||||
if (file.size > SystemModel.get('import-fps.limit')) throw new FileTooLargeError();
|
||||
const content = fs.readFileSync(this.request.files.file.filepath, 'utf-8');
|
||||
const content = await fs.readFile(file.filepath, 'utf-8');
|
||||
const result = await xml2js.parseStringPromise(content);
|
||||
tasks.push(result);
|
||||
} catch (e) {
|
||||
@@ -95,7 +95,7 @@ class FpsProblemImportHandler extends Handler {
|
||||
console.log(e);
|
||||
let zip: AdmZip;
|
||||
try {
|
||||
zip = new AdmZip(this.request.files.file.filepath);
|
||||
zip = new AdmZip(file.filepath);
|
||||
} catch (err) {
|
||||
throw new ValidationError('zip', null, err.message);
|
||||
}
|
||||
|
||||
@@ -476,8 +476,7 @@ export class ContestManagementHandler extends ContestManagementBaseHandler {
|
||||
}
|
||||
const file = this.request.files?.file;
|
||||
if (!file) throw new ValidationError('file');
|
||||
const f = statSync(file.filepath);
|
||||
const size = Math.sum((this.tdoc.files || []).map((i) => i.size)) + f.size;
|
||||
const size = Math.sum((this.tdoc.files || []).map((i) => i.size)) + file.size;
|
||||
if (size >= system.get('limit.contest_files_size')) {
|
||||
throw new FileLimitExceededError('size');
|
||||
}
|
||||
|
||||
@@ -273,8 +273,7 @@ export class HomeworkFilesHandler extends Handler {
|
||||
}
|
||||
const file = this.request.files?.file;
|
||||
if (!file) throw new ValidationError('file');
|
||||
const f = statSync(file.filepath);
|
||||
const size = Math.sum((this.tdoc.files || []).map((i) => i.size)) + f.size;
|
||||
const size = Math.sum((this.tdoc.files || []).map((i) => i.size)) + file.size;
|
||||
if (size >= system.get('limit.contest_files_size')) {
|
||||
throw new FileLimitExceededError('size');
|
||||
}
|
||||
|
||||
@@ -53,8 +53,7 @@ export class FilesHandler extends Handler {
|
||||
}
|
||||
const file = this.request.files?.file;
|
||||
if (!file) throw new ValidationError('file');
|
||||
const f = statSync(file.filepath);
|
||||
const size = Math.sum((this.user._files || []).map((i) => i.size)) + f.size;
|
||||
const size = Math.sum((this.user._files || []).map((i) => i.size)) + file.size;
|
||||
if (size >= system.get('limit.user_files_size')) {
|
||||
if (!this.user.hasPriv(PRIV.PRIV_UNLIMITED_QUOTA)) throw new FileLimitExceededError('size');
|
||||
}
|
||||
|
||||
@@ -705,13 +705,14 @@ export class ProblemFilesHandler extends ProblemDetailHandler {
|
||||
@post('filename', Types.Filename, true)
|
||||
@post('type', Types.Range(['testdata', 'additional_file']), true)
|
||||
async postUploadFile(domainId: string, filename: string, type = 'testdata') {
|
||||
if (!this.request.files.file) throw new ValidationError('file');
|
||||
filename ||= this.request.files.file.originalFilename || String.random(16);
|
||||
const file = this.request.files.file;
|
||||
if (!file) throw new ValidationError('file');
|
||||
filename ||= file.originalFilename || String.random(16);
|
||||
const files = [];
|
||||
if (filename.endsWith('.zip') && type === 'testdata') {
|
||||
let zip: AdmZip;
|
||||
try {
|
||||
zip = new AdmZip(this.request.files.file.filepath);
|
||||
zip = new AdmZip(file.filepath);
|
||||
} catch (e) {
|
||||
throw new ValidationError('zip', null, e.message);
|
||||
}
|
||||
|
||||
@@ -261,8 +261,7 @@ export class TrainingFilesHandler extends Handler {
|
||||
}
|
||||
const file = this.request.files?.file;
|
||||
if (!file) throw new ValidationError('file');
|
||||
const f = statSync(file.filepath);
|
||||
const size = Math.sum((this.tdoc.files || []).map((i) => i.size)) + f.size;
|
||||
const size = Math.sum((this.tdoc.files || []).map((i) => i.size)) + file.size;
|
||||
if (size >= system.get('limit.contest_files_size')) {
|
||||
throw new FileLimitExceededError('size');
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ export default class Watcher extends Service {
|
||||
let hasUpdate = false;
|
||||
while (index < pending.length) {
|
||||
const filename = pending[index];
|
||||
const { children } = require.cache[filename];
|
||||
const children = require.cache[filename]?.children || [];
|
||||
let isDeclined = true;
|
||||
let isAccepted = false;
|
||||
for (const { filename } of children) {
|
||||
|
||||
@@ -124,10 +124,10 @@ class ImportHojHandler extends Handler {
|
||||
}
|
||||
|
||||
async post({ domainId }) {
|
||||
if (!this.request.files.file) throw new ValidationError('file');
|
||||
const stat = await fs.stat(this.request.files.file.filepath);
|
||||
if (stat.size > 128 * 1024 * 1024) throw new ValidationError('file', 'File too large');
|
||||
await this.fromFile(domainId, this.request.files.file.filepath);
|
||||
const file = this.request.files.file;
|
||||
if (!file) throw new ValidationError('file');
|
||||
if (file.size > 128 * 1024 * 1024) throw new ValidationError('file', 'File too large');
|
||||
await this.fromFile(domainId, file.filepath);
|
||||
this.response.redirect = this.url('problem_main');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,10 +129,10 @@ class ImportQduojHandler extends Handler {
|
||||
}
|
||||
|
||||
async post({ domainId }) {
|
||||
if (!this.request.files.file) throw new ValidationError('file');
|
||||
const stat = await fs.stat(this.request.files.file.filepath);
|
||||
if (stat.size > 256 * 1024 * 1024) throw new FileTooLargeError('256m');
|
||||
await this.fromFile(domainId, this.request.files.file.filepath);
|
||||
const file = this.request.files.file;
|
||||
if (!file) throw new ValidationError('file');
|
||||
if (file.size > 256 * 1024 * 1024) throw new FileTooLargeError('256m');
|
||||
await this.fromFile(domainId, file.filepath);
|
||||
this.response.redirect = this.url('problem_main');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user