diff --git a/nuxt.config.ts b/nuxt.config.ts index 5631081..6795314 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -25,7 +25,7 @@ export default defineNuxtConfig({ minio: { endPoint: "s3.portnimara.com", port: 9000, - useSSL: true, + useSSL: false, accessKey: "279QFJV96Ja9wNB0YYmU1W3Pv4Ofeh3pxojcz0pzeC5LjRurq", secretKey: "y8ze6nmA2VHJWDsIU1eNEBq4R4WlmJWp97UE0zUR7E4zWLS6O", bucketName: "client-portal", diff --git a/server/api/files/list.ts b/server/api/files/list.ts index 33a86f3..77b2d45 100644 --- a/server/api/files/list.ts +++ b/server/api/files/list.ts @@ -2,12 +2,17 @@ import { listFiles } from '~/server/utils/minio'; export default defineEventHandler(async (event) => { try { + console.log('List files API called'); const query = getQuery(event); const prefix = (query.prefix as string) || ''; const recursive = query.recursive === 'true'; + console.log('Listing files with prefix:', prefix, 'recursive:', recursive); + const files = await listFiles(prefix, recursive); + console.log('Files retrieved:', files.length); + // Format file list with additional metadata const formattedFiles = (files as any[]).map(file => ({ ...file, @@ -30,11 +35,13 @@ export default defineEventHandler(async (event) => { count: formattedFiles.length, currentPath: prefix, }; - } catch (error) { - console.error('Failed to list files:', error); + } catch (error: any) { + console.error('Failed to list files - Full error:', error); + console.error('Error message:', error.message); + console.error('Error stack:', error.stack); throw createError({ statusCode: 500, - statusMessage: 'Failed to list files', + statusMessage: error.message || 'Failed to list files', }); } }); diff --git a/server/api/files/test-connection.ts b/server/api/files/test-connection.ts new file mode 100644 index 0000000..9993d15 --- /dev/null +++ b/server/api/files/test-connection.ts @@ -0,0 +1,62 @@ +export default defineEventHandler(async (event) => { + try { + const config = useRuntimeConfig().minio; + + // Log configuration (without secrets) + const configInfo = { + endPoint: config.endPoint, + port: config.port, + useSSL: config.useSSL, + bucketName: config.bucketName, + hasAccessKey: !!config.accessKey, + hasSecretKey: !!config.secretKey, + accessKeyLength: config.accessKey?.length || 0, + secretKeyLength: config.secretKey?.length || 0, + }; + + console.log('Testing MinIO connection with config:', configInfo); + + // Import MinIO client + const { Client } = await import('minio'); + + // Create client + const client = new Client({ + endPoint: config.endPoint, + port: parseInt(config.port), + useSSL: config.useSSL, + accessKey: config.accessKey, + secretKey: config.secretKey, + }); + + // Test bucket exists + const bucketExists = await client.bucketExists(config.bucketName); + console.log(`Bucket ${config.bucketName} exists:`, bucketExists); + + // If bucket doesn't exist, try to create it + if (!bucketExists) { + console.log(`Attempting to create bucket ${config.bucketName}`); + await client.makeBucket(config.bucketName, 'us-east-1'); + console.log(`Bucket ${config.bucketName} created successfully`); + } + + // List buckets to verify connection + const buckets = await client.listBuckets(); + console.log('Available buckets:', buckets.map(b => b.name)); + + return { + success: true, + connection: 'successful', + config: configInfo, + bucketExists, + availableBuckets: buckets.map(b => b.name), + }; + } catch (error: any) { + console.error('MinIO connection test failed:', error); + return { + success: false, + error: error.message, + stack: error.stack, + code: error.code, + }; + } +}); diff --git a/server/utils/minio.ts b/server/utils/minio.ts index ba2a28f..b46bf2d 100644 --- a/server/utils/minio.ts +++ b/server/utils/minio.ts @@ -5,6 +5,15 @@ import type { BucketItem } from 'minio'; export const getMinioClient = () => { const config = useRuntimeConfig().minio; + console.log('MinIO Config:', { + endPoint: config.endPoint, + port: config.port, + useSSL: config.useSSL, + bucketName: config.bucketName, + hasAccessKey: !!config.accessKey, + hasSecretKey: !!config.secretKey, + }); + return new Client({ endPoint: config.endPoint, port: config.port, @@ -19,59 +28,87 @@ export const listFiles = async (prefix: string = '', recursive: boolean = false) const client = getMinioClient(); const bucketName = useRuntimeConfig().minio.bucketName; + console.log(`Listing files from bucket: ${bucketName}, prefix: ${prefix}, recursive: ${recursive}`); + const files: any[] = []; const folders = new Set(); - return new Promise((resolve, reject) => { - const stream = client.listObjectsV2(bucketName, prefix, recursive); - - stream.on('data', (obj) => { - if (!recursive && prefix) { - // Extract folder structure when not recursive - const relativePath = obj.name.substring(prefix.length); - const firstSlash = relativePath.indexOf('/'); - - if (firstSlash > -1) { - // This is a folder - const folderName = relativePath.substring(0, firstSlash); - folders.add(prefix + folderName + '/'); - } else if (relativePath) { - // This is a file in the current folder - files.push({ - name: obj.name, - size: obj.size, - lastModified: obj.lastModified, - etag: obj.etag, - isFolder: false, - }); - } - } else { - // When recursive or at root, include all files - if (!obj.name.endsWith('/')) { - files.push({ - name: obj.name, - size: obj.size, - lastModified: obj.lastModified, - etag: obj.etag, - isFolder: false, - }); - } - } - }); - - stream.on('error', reject); - stream.on('end', () => { - // Add folders to the result - const folderItems = Array.from(folders).map(folder => ({ - name: folder, - size: 0, - lastModified: new Date(), - etag: '', - isFolder: true, - })); + return new Promise(async (resolve, reject) => { + try { + // First check if bucket exists + const bucketExists = await client.bucketExists(bucketName); + console.log(`Bucket ${bucketName} exists:`, bucketExists); - resolve([...folderItems, ...files]); - }); + if (!bucketExists) { + console.error(`Bucket ${bucketName} does not exist`); + reject(new Error(`Bucket ${bucketName} does not exist`)); + return; + } + + const stream = client.listObjectsV2(bucketName, prefix, recursive); + let objectCount = 0; + + stream.on('data', (obj) => { + objectCount++; + console.log('Object found:', obj.name); + + if (!recursive && prefix) { + // Extract folder structure when not recursive + const relativePath = obj.name.substring(prefix.length); + const firstSlash = relativePath.indexOf('/'); + + if (firstSlash > -1) { + // This is a folder + const folderName = relativePath.substring(0, firstSlash); + folders.add(prefix + folderName + '/'); + } else if (relativePath) { + // This is a file in the current folder + files.push({ + name: obj.name, + size: obj.size, + lastModified: obj.lastModified, + etag: obj.etag, + isFolder: false, + }); + } + } else { + // When recursive or at root, include all files + if (!obj.name.endsWith('/')) { + files.push({ + name: obj.name, + size: obj.size, + lastModified: obj.lastModified, + etag: obj.etag, + isFolder: false, + }); + } + } + }); + + stream.on('error', (error) => { + console.error('Stream error:', error); + reject(error); + }); + + stream.on('end', () => { + console.log(`Stream ended. Total objects processed: ${objectCount}`); + + // Add folders to the result + const folderItems = Array.from(folders).map(folder => ({ + name: folder, + size: 0, + lastModified: new Date(), + etag: '', + isFolder: true, + })); + + console.log(`Returning ${folderItems.length} folders and ${files.length} files`); + resolve([...folderItems, ...files]); + }); + } catch (error) { + console.error('Error in listFiles:', error); + reject(error); + } }); };