KI-AGENT: Interne MinIO-Links durch Backend-Downloads ersetzen
This commit is contained in:
@@ -177,11 +177,49 @@ export default async function exportRoutes(server: FastifyInstance) {
|
||||
.from(generatedexports)
|
||||
.where(eq(generatedexports.tenantId, req.user.tenant_id))
|
||||
|
||||
console.log(data)
|
||||
reply.send(data)
|
||||
reply.send(data.map(item => ({
|
||||
...item,
|
||||
url: `/api/exports/${item.id}/download`,
|
||||
})))
|
||||
|
||||
})
|
||||
|
||||
server.get("/exports/:id/download", async (req, reply) => {
|
||||
const { id } = req.params as { id: string }
|
||||
const exportId = Number(id)
|
||||
if (!Number.isSafeInteger(exportId)) {
|
||||
return reply.code(404).send({ error: "Export not found" })
|
||||
}
|
||||
|
||||
const [item] = await server.db
|
||||
.select()
|
||||
.from(generatedexports)
|
||||
.where(eq(generatedexports.id, exportId))
|
||||
|
||||
if (
|
||||
!item ||
|
||||
item.tenantId !== req.user.tenant_id ||
|
||||
item.validUntil.getTime() <= Date.now()
|
||||
) {
|
||||
return reply.code(404).send({ error: "Export not found" })
|
||||
}
|
||||
|
||||
try {
|
||||
const { Body, ContentType } = await s3.send(new GetObjectCommand({
|
||||
Bucket: secrets.S3_BUCKET,
|
||||
Key: item.filePath,
|
||||
}))
|
||||
const filename = item.filePath.split("/").pop() || `export-${item.id}`
|
||||
|
||||
reply.header("Content-Type", ContentType || "application/octet-stream")
|
||||
reply.header("Content-Disposition", `attachment; filename="${filename}"`)
|
||||
return reply.send(Body as any)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
return reply.code(500).send({ error: "Could not download export" })
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ import { s3 } from "../utils/s3"
|
||||
import {
|
||||
GetObjectCommand
|
||||
} from "@aws-sdk/client-s3"
|
||||
import { getSignedUrl } from "@aws-sdk/s3-request-presigner"
|
||||
import archiver from "archiver"
|
||||
import { secrets } from "../utils/secrets"
|
||||
import { saveFile } from "../utils/files"
|
||||
@@ -241,6 +240,28 @@ export default async function fileRoutes(server: FastifyInstance) {
|
||||
}
|
||||
})
|
||||
|
||||
// Dateien über das Backend ausliefern, damit interne S3-Endpunkte wie
|
||||
// http://minio:9000 niemals als URL an den Browser gelangen.
|
||||
server.get("/files/content/:id", async (req, reply) => {
|
||||
try {
|
||||
const { id } = req.params as { id: string }
|
||||
const file = await loadSingleFileForRequest(req, id)
|
||||
if (!file) return reply.code(404).send({ error: "File not found" })
|
||||
|
||||
const { Body, ContentType } = await s3.send(new GetObjectCommand({
|
||||
Bucket: secrets.S3_BUCKET,
|
||||
Key: file.path!
|
||||
}))
|
||||
|
||||
reply.header("Content-Type", ContentType || "application/octet-stream")
|
||||
reply.header("Content-Disposition", "inline")
|
||||
return reply.send(Body as any)
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
return reply.code(500).send({ error: "Could not load file" })
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
|
||||
// -------------------------------------------------------------
|
||||
@@ -261,13 +282,7 @@ export default async function fileRoutes(server: FastifyInstance) {
|
||||
const file = await loadSingleFileForRequest(req, id)
|
||||
if (!file) return reply.code(404).send({ error: "Not found" })
|
||||
|
||||
const url = await getSignedUrl(
|
||||
s3,
|
||||
new GetObjectCommand({ Bucket: secrets.S3_BUCKET, Key: file.path! }),
|
||||
{ expiresIn: 900 }
|
||||
)
|
||||
|
||||
return { ...file, url }
|
||||
return { ...file, url: `/api/files/content/${file.id}` }
|
||||
} else {
|
||||
// -------------------------------------------------
|
||||
// MULTIPLE PRESIGNED URLs
|
||||
@@ -283,26 +298,10 @@ export default async function fileRoutes(server: FastifyInstance) {
|
||||
|
||||
const selected = rows.filter(f => ids.includes(f.id) && f.path)
|
||||
|
||||
console.log(selected)
|
||||
|
||||
const url = await getSignedUrl(
|
||||
s3,
|
||||
new GetObjectCommand({ Bucket: secrets.S3_BUCKET, Key: selected[0].path! }),
|
||||
{ expiresIn: 900 }
|
||||
)
|
||||
console.log(url)
|
||||
console.log(selected.filter(f => !f.path))
|
||||
|
||||
const output = await Promise.all(
|
||||
selected.map(async (file) => {
|
||||
const url = await getSignedUrl(
|
||||
s3,
|
||||
new GetObjectCommand({ Bucket: secrets.S3_BUCKET, Key: file.path! }),
|
||||
{ expiresIn: 900 }
|
||||
)
|
||||
return { ...file, url }
|
||||
})
|
||||
)
|
||||
const output = selected.map(file => ({
|
||||
...file,
|
||||
url: `/api/files/content/${file.id}`
|
||||
}))
|
||||
|
||||
return { files: output }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user