mirror of https://github.com/ghostfolio/ghostfolio
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
101 lines
2.6 KiB
101 lines
2.6 KiB
import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service';
|
|
|
|
import { HttpException, Injectable } from '@nestjs/common';
|
|
import { DocumentType } from '@prisma/client';
|
|
import { StatusCodes, getReasonPhrase } from 'http-status-codes';
|
|
import { createReadStream, existsSync } from 'node:fs';
|
|
import { mkdir } from 'node:fs/promises';
|
|
import { join } from 'node:path';
|
|
|
|
@Injectable()
|
|
export class UploadService {
|
|
private readonly uploadDir: string;
|
|
|
|
public constructor(private readonly prismaService: PrismaService) {
|
|
this.uploadDir = process.env.UPLOAD_DIR || join(process.cwd(), 'uploads');
|
|
}
|
|
|
|
public async ensureUploadDir(): Promise<void> {
|
|
if (!existsSync(this.uploadDir)) {
|
|
await mkdir(this.uploadDir, { recursive: true });
|
|
}
|
|
}
|
|
|
|
public getUploadDir(): string {
|
|
return this.uploadDir;
|
|
}
|
|
|
|
public async createDocument({
|
|
entityId,
|
|
file,
|
|
name,
|
|
partnershipId,
|
|
taxYear,
|
|
type
|
|
}: {
|
|
entityId?: string;
|
|
file: any;
|
|
name?: string;
|
|
partnershipId?: string;
|
|
taxYear?: number;
|
|
type: DocumentType;
|
|
}) {
|
|
await this.ensureUploadDir();
|
|
|
|
const now = new Date();
|
|
const yearDir = now.getFullYear().toString();
|
|
const monthDir = (now.getMonth() + 1).toString().padStart(2, '0');
|
|
const subDir = join(this.uploadDir, yearDir, monthDir);
|
|
|
|
if (!existsSync(subDir)) {
|
|
await mkdir(subDir, { recursive: true });
|
|
}
|
|
|
|
const relativePath = `${yearDir}/${monthDir}/${file.filename}`;
|
|
|
|
return this.prismaService.document.create({
|
|
data: {
|
|
entityId: entityId || undefined,
|
|
filePath: relativePath,
|
|
fileSize: file.size,
|
|
mimeType: file.mimetype,
|
|
name: name || file.originalname,
|
|
partnershipId: partnershipId || undefined,
|
|
taxYear: taxYear ? Number(taxYear) : undefined,
|
|
type
|
|
}
|
|
});
|
|
}
|
|
|
|
public async getDocumentById(documentId: string) {
|
|
const document = await this.prismaService.document.findUnique({
|
|
where: { id: documentId }
|
|
});
|
|
|
|
if (!document) {
|
|
throw new HttpException(
|
|
getReasonPhrase(StatusCodes.NOT_FOUND),
|
|
StatusCodes.NOT_FOUND
|
|
);
|
|
}
|
|
|
|
return document;
|
|
}
|
|
|
|
public async getDocumentStream(documentId: string) {
|
|
const document = await this.getDocumentById(documentId);
|
|
const fullPath = join(this.uploadDir, document.filePath);
|
|
|
|
if (!existsSync(fullPath)) {
|
|
throw new HttpException(
|
|
getReasonPhrase(StatusCodes.NOT_FOUND),
|
|
StatusCodes.NOT_FOUND
|
|
);
|
|
}
|
|
|
|
return {
|
|
document,
|
|
stream: createReadStream(fullPath)
|
|
};
|
|
}
|
|
}
|
|
|