mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-27 22:30:55 +00:00
Refactor file handling to improve URL safety and enhance file viewing capabilities across components
This commit is contained in:
@@ -12,6 +12,20 @@ export interface CreateFileInput {
|
||||
file: Express.Multer.File;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a filename safe to use as a MinIO object-key segment: collapse runs of
|
||||
* spaces/unsafe characters to a single underscore while keeping the dot before
|
||||
* the extension. Prevents percent-encoding mismatches between the stored URL
|
||||
* and the actual object key.
|
||||
*/
|
||||
function sanitizeObjectName(name: string): string {
|
||||
return name
|
||||
.normalize("NFKD")
|
||||
.replace(/[^\w.\-]+/g, "_")
|
||||
.replace(/_{2,}/g, "_")
|
||||
.replace(/^_+|_+$/g, "");
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class FilesService {
|
||||
constructor(
|
||||
@@ -21,7 +35,12 @@ export class FilesService {
|
||||
|
||||
async upload(input: CreateFileInput): Promise<FileRecord> {
|
||||
const { resourceId, resource, code, file } = input;
|
||||
const objectName = `${resource}/${resourceId}/${Date.now()}_${file.originalname}`;
|
||||
// Keep the object key URL-safe so it survives the round-trip through the
|
||||
// stored URL (spaces/unicode in the original name would otherwise be
|
||||
// percent-encoded in the URL and no longer match the MinIO key). The
|
||||
// human-readable name is preserved separately on the record below.
|
||||
const safeName = sanitizeObjectName(file.originalname);
|
||||
const objectName = `${resource}/${resourceId}/${Date.now()}_${safeName}`;
|
||||
const url = await this.minioService.uploadFile(objectName, file.buffer, file.mimetype);
|
||||
|
||||
return this.filesRepository.create({
|
||||
|
||||
@@ -65,7 +65,14 @@ export class MinioService {
|
||||
}
|
||||
|
||||
const url = new URL(trimmed);
|
||||
const parts = url.pathname.split("/").filter(Boolean);
|
||||
// `url.pathname` percent-encodes the object key (e.g. a space becomes
|
||||
// "%20"), but MinIO stores the key with its literal characters. Decode each
|
||||
// segment so the recovered key matches what was uploaded — otherwise a file
|
||||
// whose name had spaces/unicode 404s with "specified key does not exist".
|
||||
const parts = url.pathname
|
||||
.split("/")
|
||||
.filter(Boolean)
|
||||
.map((segment) => decodeURIComponent(segment));
|
||||
if (parts[0] === this.bucket) {
|
||||
parts.shift();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user