fix: file access
This commit is contained in:
parent
5c8bc90bcc
commit
0b6bb5662c
|
|
@ -65,6 +65,7 @@ services:
|
|||
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
|
||||
MINIO_BROWSER_REDIRECT_URL: http://localhost:9001
|
||||
MINIO_SERVER_URL: http://localhost:9000
|
||||
MINIO_DOMAIN: localhost
|
||||
# CRITICAL: SNMD command for full S3 compatibility
|
||||
command: server /data{1...4} --console-address ":9001"
|
||||
healthcheck:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,11 @@
|
|||
@base = http://localhost:3000
|
||||
|
||||
|
||||
### Health
|
||||
|
||||
GET {{base}}/health
|
||||
|
||||
|
||||
### Info
|
||||
|
||||
GET {{base}}/api/info
|
||||
|
|
@ -30,15 +36,8 @@ POST {{base}}/api/text-to-image
|
|||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"prompt": "банановый стимпанк. много стимпанк машин и меаханизмов посвященных бананм и работающих на бананах. банановая феерия",
|
||||
"filename": "banatie-party",
|
||||
"autoEnhance": true,
|
||||
"enhancementOptions": {
|
||||
"imageStyle": "photorealistic",
|
||||
"aspectRatio": "landscape",
|
||||
"mood": "peaceful",
|
||||
"lighting": "golden hour"
|
||||
}
|
||||
"prompt": "A majestic eagle soaring over snow-capped mountains",
|
||||
"filename": "test-eagle"
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -24,54 +24,37 @@ imagesRouter.get(
|
|||
const storageService = StorageFactory.getInstance();
|
||||
|
||||
try {
|
||||
// Method 1: Redirect to presigned URL (24 hour expiry)
|
||||
const presignedUrl = await storageService.getPresignedDownloadUrl(
|
||||
// Stream the file directly through our API (more reliable than presigned URL redirects)
|
||||
const fileBuffer = await storageService.downloadFile(
|
||||
orgId,
|
||||
projectId,
|
||||
category as 'uploads' | 'generated' | 'references',
|
||||
filename,
|
||||
24 * 60 * 60 // 24 hours
|
||||
filename
|
||||
);
|
||||
|
||||
// Redirect to the presigned URL
|
||||
return res.redirect(302, presignedUrl);
|
||||
// Determine content type from filename
|
||||
const ext = filename.toLowerCase().split('.').pop();
|
||||
const contentType = {
|
||||
'png': 'image/png',
|
||||
'jpg': 'image/jpeg',
|
||||
'jpeg': 'image/jpeg',
|
||||
'gif': 'image/gif',
|
||||
'webp': 'image/webp',
|
||||
'svg': 'image/svg+xml'
|
||||
}[ext || ''] || 'application/octet-stream';
|
||||
|
||||
res.setHeader('Content-Type', contentType);
|
||||
res.setHeader('Cache-Control', 'public, max-age=86400'); // 24 hours
|
||||
res.setHeader('Content-Length', fileBuffer.length);
|
||||
|
||||
return res.send(fileBuffer);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Failed to generate presigned URL:', error);
|
||||
|
||||
try {
|
||||
// Method 2: Fallback - Stream the file directly through our API
|
||||
const fileBuffer = await storageService.downloadFile(
|
||||
orgId,
|
||||
projectId,
|
||||
category as 'uploads' | 'generated' | 'references',
|
||||
filename
|
||||
);
|
||||
|
||||
// Determine content type from filename
|
||||
const ext = filename.toLowerCase().split('.').pop();
|
||||
const contentType = {
|
||||
'png': 'image/png',
|
||||
'jpg': 'image/jpeg',
|
||||
'jpeg': 'image/jpeg',
|
||||
'gif': 'image/gif',
|
||||
'webp': 'image/webp',
|
||||
'svg': 'image/svg+xml'
|
||||
}[ext || ''] || 'application/octet-stream';
|
||||
|
||||
res.setHeader('Content-Type', contentType);
|
||||
res.setHeader('Cache-Control', 'public, max-age=86400'); // 24 hours
|
||||
res.setHeader('Content-Length', fileBuffer.length);
|
||||
|
||||
return res.send(fileBuffer);
|
||||
|
||||
} catch (streamError) {
|
||||
console.error('Failed to stream file:', streamError);
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'File not found'
|
||||
});
|
||||
}
|
||||
console.error('Failed to stream file:', error);
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'File not found'
|
||||
});
|
||||
}
|
||||
})
|
||||
);
|
||||
|
|
|
|||
|
|
@ -181,7 +181,20 @@ export class MinioStorageService implements StorageService {
|
|||
expirySeconds: number = 86400 // 24 hours default
|
||||
): Promise<string> {
|
||||
const filePath = this.getFilePath(orgId, projectId, category, filename);
|
||||
return await this.client.presignedGetObject(this.bucketName, filePath, expirySeconds);
|
||||
const presignedUrl = await this.client.presignedGetObject(this.bucketName, filePath, expirySeconds);
|
||||
|
||||
// Replace internal Docker hostname with public URL if configured
|
||||
if (this.publicUrl) {
|
||||
const clientEndpoint = this.client.host + (this.client.port ? `:${this.client.port}` : '');
|
||||
const publicEndpoint = this.publicUrl.replace(/^https?:\/\//, '');
|
||||
|
||||
return presignedUrl.replace(
|
||||
`${this.client.protocol}//${clientEndpoint}`,
|
||||
this.publicUrl
|
||||
);
|
||||
}
|
||||
|
||||
return presignedUrl;
|
||||
}
|
||||
|
||||
async listProjectFiles(
|
||||
|
|
|
|||
Loading…
Reference in New Issue