mirror of
https://github.com/certd/certd.git
synced 2026-06-27 14:07:33 +08:00
93 lines
2.9 KiB
TypeScript
93 lines
2.9 KiB
TypeScript
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";
|
|
|
|
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) {
|
|
return imageExtSet.has(filePath.substring(filePath.lastIndexOf(".")).toLowerCase());
|
|
}
|
|
|
|
export function getImageDownloadOptions(filePath: string) {
|
|
if (!isImageFile(filePath)) {
|
|
return undefined;
|
|
}
|
|
return {
|
|
maxage: imageCacheSeconds * 1000,
|
|
setHeaders(res: any) {
|
|
res.setHeader("Cache-Control", `public,max-age=${imageCacheSeconds}`);
|
|
},
|
|
};
|
|
}
|
|
|
|
/**
|
|
*/
|
|
@Provide()
|
|
@Controller("/api/basic/file")
|
|
export class FileController extends BaseController {
|
|
@Inject()
|
|
fileService: FileService;
|
|
|
|
@Inject()
|
|
authService: AuthService;
|
|
|
|
@Post("/upload", { description: Constants.per.authOnly })
|
|
async upload(@Files() files: UploadFileInfo<string>[], @Fields() fields: any, @Query("autoSave") autoSave: string) {
|
|
console.log("files", files, fields);
|
|
const cacheKey = uploadTmpFileCacheKey + nanoid();
|
|
const file = files[0];
|
|
cache.set(
|
|
cacheKey,
|
|
{
|
|
filename: file.filename,
|
|
tmpFilePath: file.data,
|
|
} as UploadFileItem,
|
|
{
|
|
ttl: 1000 * 60 * 60,
|
|
}
|
|
);
|
|
if (autoSave === "true") {
|
|
const key = await this.fileService.saveFile(this.getUserId(), cacheKey, "public");
|
|
return this.ok({
|
|
key,
|
|
url: `/api/basic/file/download?key=${encodeURIComponent(key as string)}`,
|
|
});
|
|
}
|
|
return this.ok({
|
|
key: cacheKey,
|
|
});
|
|
}
|
|
|
|
@Get("/download", { description: Constants.per.guestOptionalAuth })
|
|
async download(@Query("key") key: string) {
|
|
const filePath = this.getDownloadFilePath(key);
|
|
const sendOptions = getImageDownloadOptions(filePath);
|
|
if (!sendOptions) {
|
|
this.ctx.response.attachment(filePath);
|
|
}
|
|
await send(this.ctx, filePath, sendOptions);
|
|
}
|
|
|
|
private getDownloadFilePath(key: string) {
|
|
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;
|
|
}
|
|
}
|
|
}
|