Files
FEDEO/backend/src/utils/files.ts
2026-03-16 20:46:26 +01:00

117 lines
3.9 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { PutObjectCommand } from "@aws-sdk/client-s3"
import { s3 } from "./s3"
import { secrets } from "./secrets"
// Drizzle schema
import { files } from "../../db/schema"
import { eq } from "drizzle-orm"
import { FastifyInstance } from "fastify"
import { storeExtractedTextForFile } from "./documentText"
export const saveFile = async (
server: FastifyInstance,
tenant: number,
messageId: string | number | null, // Typ angepasst (oft null bei manueller Gen)
attachment: any, // Kann File, Buffer oder Mailparser-Objekt sein
folder: string | null,
type: string | null,
other: Record<string, any> = {}
) => {
try {
const {
filename: providedFilename,
filesize: _providedFilesize,
mimeType: providedMimeType,
...dbFields
} = other
// ---------------------------------------------------
// 1⃣ FILE ENTRY ANLEGEN
// ---------------------------------------------------
const insertRes = await server.db
.insert(files)
.values({
tenant,
folder,
type,
...dbFields
})
.returning()
const created = insertRes?.[0]
if (!created) {
console.error("File creation failed (no row returned)")
return null
}
// Name ermitteln (Fallback Logik)
// Wenn attachment ein Buffer ist, muss der Name in 'other' stehen oder generiert werden
const filename = attachment.filename || providedFilename || `${created.id}.pdf`
// ---------------------------------------------------
// 2⃣ BODY & CONTENT TYPE ERMITTELN
// ---------------------------------------------------
let body: Buffer | Uint8Array | string
let contentType = providedMimeType || "application/octet-stream"
if (Buffer.isBuffer(attachment)) {
// FALL 1: RAW BUFFER (von finishManualGeneration)
body = attachment
// ContentType wurde oben schon über 'type' Parameter gesetzt (z.B. application/pdf)
} else if (typeof File !== "undefined" && attachment instanceof File) {
// FALL 2: BROWSER FILE
body = Buffer.from(await attachment.arrayBuffer())
contentType = attachment.type || contentType
} else if (attachment.content) {
// FALL 3: MAILPARSER OBJECT
body = attachment.content
contentType = attachment.contentType || contentType
} else {
console.error("saveFile: Unknown attachment format")
return null
}
// ---------------------------------------------------
// 3⃣ S3 UPLOAD
// ---------------------------------------------------
const key = `${tenant}/filesbyid/${created.id}/${filename}`
await s3.send(
new PutObjectCommand({
Bucket: secrets.S3_BUCKET,
Key: key,
Body: body,
ContentType: contentType,
ContentLength: body.length // <--- WICHTIG: Behebt den AWS Fehler
})
)
// ---------------------------------------------------
// 4⃣ PATH IN DB SETZEN
// ---------------------------------------------------
await server.db
.update(files)
.set({
path: key,
mimeType: contentType,
name: filename,
size: body.length
})
.where(eq(files.id, created.id))
await storeExtractedTextForFile(
server,
created.id,
Buffer.isBuffer(body) ? body : Buffer.from(body),
contentType,
filename
)
console.log(`File saved: ${key}`)
return { id: created.id, key }
} catch (err) {
console.error("saveFile error:", err)
return null
}
}