Files
certd/packages/ui/certd-server/src/controller/basic/file-controller.ts
T

93 lines
2.9 KiB
TypeScript
Raw Normal View History

2026-05-31 01:41:33 +08:00
import { Controller, Fields, Files, Get, Inject, Post, Provide, Query } from "@midwayjs/core";
import { BaseController, Constants, FileService, PermissionException, UploadFileItem, uploadTmpFileCacheKey } from "@certd/lib-server";
import send from "koa-send";
import { nanoid } from "nanoid";
import { cache } from "@certd/basic";
import { UploadFileInfo } from "@midwayjs/upload";
import { AuthService } from "../../modules/sys/authority/service/auth-service.js";
2024-10-05 01:46:25 +08:00
2026-05-31 01:41:33 +08:00
const imageExtSet = new Set([".apng", ".avif", ".bmp", ".gif", ".ico", ".jpeg", ".jpg", ".png", ".svg", ".webp"]);
const imageCacheSeconds = 3 * 24 * 60 * 60;
export function isImageFile(filePath: string) {
2026-05-31 01:41:33 +08:00
return imageExtSet.has(filePath.substring(filePath.lastIndexOf(".")).toLowerCase());
}
2026-05-15 00:39:35 +08:00
export function getImageDownloadOptions(filePath: string) {
if (!isImageFile(filePath)) {
return undefined;
}
return {
maxage: imageCacheSeconds * 1000,
setHeaders(res: any) {
2026-05-31 01:41:33 +08:00
res.setHeader("Cache-Control", `public,max-age=${imageCacheSeconds}`);
2026-05-15 00:39:35 +08:00
},
};
}
2024-10-05 01:46:25 +08:00
/**
*/
@Provide()
2026-05-31 01:41:33 +08:00
@Controller("/api/basic/file")
2024-10-05 01:46:25 +08:00
export class FileController extends BaseController {
@Inject()
fileService: FileService;
@Inject()
authService: AuthService;
2026-05-31 01:41:33 +08:00
@Post("/upload", { description: Constants.per.authOnly })
async upload(@Files() files: UploadFileInfo<string>[], @Fields() fields: any, @Query("autoSave") autoSave: string) {
console.log("files", files, fields);
2024-10-05 01:46:25 +08:00
const cacheKey = uploadTmpFileCacheKey + nanoid();
const file = files[0];
cache.set(
cacheKey,
{
filename: file.filename,
tmpFilePath: file.data,
} as UploadFileItem,
{
ttl: 1000 * 60 * 60,
}
);
2026-05-31 01:41:33 +08:00
if (autoSave === "true") {
const key = await this.fileService.saveFile(this.getUserId(), cacheKey, "public");
2026-05-26 01:08:17 +08:00
return this.ok({
key,
url: `/api/basic/file/download?key=${encodeURIComponent(key)}`,
});
}
2024-10-05 01:46:25 +08:00
return this.ok({
key: cacheKey,
});
}
2026-05-31 01:41:33 +08:00
@Get("/download", { description: Constants.per.guestOptionalAuth })
async download(@Query("key") key: string) {
const filePath = this.getDownloadFilePath(key);
2026-05-15 00:39:35 +08:00
const sendOptions = getImageDownloadOptions(filePath);
if (!sendOptions) {
this.ctx.response.attachment(filePath);
}
2026-05-15 00:39:35 +08:00
await send(this.ctx, filePath, sendOptions);
2024-10-05 01:46:25 +08:00
}
private getDownloadFilePath(key: string) {
2026-05-31 01:41:33 +08:00
const isPrivateFile = !key.startsWith("/public");
const userId = isPrivateFile ? this.getUserId() : null;
try {
return this.fileService.getFile(key, userId);
} catch (e) {
if (!(e instanceof PermissionException) || !isPrivateFile || !this.authService.isAdmin(this.ctx)) {
throw e;
}
const adminFilePath = this.fileService.getFile(key, userId, true);
if (!isImageFile(adminFilePath)) {
throw e;
}
return adminFilePath;
}
}
2024-10-05 01:46:25 +08:00
}