Files
speckle-server/packages/fileimport-service/src/controller/filesApi.ts
T
2025-06-23 13:45:26 +01:00

102 lines
2.4 KiB
TypeScript

import { ensureError } from '@speckle/shared'
import fs from 'fs'
import path from 'node:path'
import { pipeline } from 'node:stream/promises'
import { Logger } from 'pino'
export async function downloadFile({
speckleServerUrl,
fileId,
streamId,
token,
destination,
logger
}: {
speckleServerUrl: string
fileId: string
streamId: string
token: string
destination: string
logger: Logger
}) {
const boundLogger = logger.child({
fileId,
streamId
})
try {
fs.mkdirSync(path.dirname(destination), { recursive: true })
} catch (e) {
throw ensureError(e, 'Unknown error while creating directory')
}
const downloadUrl = new URL(
`/api/stream/${streamId}/blob/${fileId}`,
speckleServerUrl
)
boundLogger.info(
{ destinationFile: destination, downloadUrl: downloadUrl.toString() },
'Downloading file {fileId} (project: {streamId}) from {downloadUrl} to {destinationFile}'
)
let response
try {
response = await fetch(downloadUrl.toString(), {
headers: {
Authorization: `Bearer ${token}`
}
})
} catch (e) {
throw ensureError(e, 'Unknown error while fetching file')
}
if (response === undefined || !response.ok) {
boundLogger.error(
{ downloadUrl, status: response?.status, statusText: response?.statusText },
'Failed to download file {fileId} from {downloadUrl}. HTTP {status}: {statusText}'
)
throw new Error(
`Failed to download file ${fileId}. HTTP ${response?.status}: ${response?.statusText}`
)
}
if (!response.body) {
throw new Error('Response body is undefined')
}
const writer = fs.createWriteStream(destination)
//handle errors
writer.on('error', (err) => {
boundLogger.error(ensureError(err), `Error writing file ${destination}`)
throw err
})
//handle completion
writer.on('finish', () => {
boundLogger.info(`File written to ${destination}`)
})
await pipeline(response.body, writer, { end: true })
}
export async function getFileInfoByName({
speckleServerUrl,
fileName,
streamId,
token
}: {
speckleServerUrl: string
fileName: string
streamId: string
token: string
}) {
const response = await fetch(
`${speckleServerUrl}/api/stream/${streamId}/blobs?fileName=${fileName}`,
{
headers: {
Authorization: `Bearer ${token}`
}
}
)
return response.json() as Promise<{ blobs: { id: string }[] }>
}