diff --git a/frontend/src/hooks/tools/shared/useToolOperation.ts b/frontend/src/hooks/tools/shared/useToolOperation.ts index d193a2d55..b5360d979 100644 --- a/frontend/src/hooks/tools/shared/useToolOperation.ts +++ b/frontend/src/hooks/tools/shared/useToolOperation.ts @@ -117,7 +117,7 @@ export const useToolOperation = ( // Composed hooks const { state, actions } = useToolState(); const { processFiles, cancelOperation: cancelApiCalls } = useToolApiCalls(); - const { generateThumbnails, createDownloadInfo, cleanupBlobUrls } = useToolResources(); + const { generateThumbnails, createDownloadInfo, cleanupBlobUrls, extractZipFiles, extractAllZipFiles } = useToolResources(); const executeOperation = useCallback(async ( params: TParams, @@ -172,7 +172,12 @@ export const useToolOperation = ( // Handle response based on responseHandler if (config.responseHandler?.type === 'zip' && config.responseHandler?.useZipExtractor) { // Use tool resources for ZIP extraction - processedFiles = await toolResources.extractZipFiles(response.data); + processedFiles = await extractZipFiles(response.data); + + if (processedFiles.length === 0) { + // Try the generic extraction as fallback + processedFiles = await extractAllZipFiles(response.data); + } } else { // Single file response const filename = validFiles.length === 1 @@ -227,7 +232,7 @@ export const useToolOperation = ( actions.setLoading(false); actions.setProgress(null); } - }, [t, config, actions, recordOperation, markOperationApplied, markOperationFailed, addFiles, processFiles, generateThumbnails, createDownloadInfo, cleanupBlobUrls]); + }, [t, config, actions, recordOperation, markOperationApplied, markOperationFailed, addFiles, processFiles, generateThumbnails, createDownloadInfo, cleanupBlobUrls, extractZipFiles, extractAllZipFiles]); const cancelOperation = useCallback(() => { cancelApiCalls(); diff --git a/frontend/src/hooks/tools/shared/useToolResources.ts b/frontend/src/hooks/tools/shared/useToolResources.ts index d603212cd..69f48fe20 100644 --- a/frontend/src/hooks/tools/shared/useToolResources.ts +++ b/frontend/src/hooks/tools/shared/useToolResources.ts @@ -2,6 +2,7 @@ import { useState, useCallback, useEffect } from 'react'; import { generateThumbnailForFile } from '../../../utils/thumbnailUtils'; import { zipFileService } from '../../../services/zipFileService'; + export const useToolResources = () => { const [blobUrls, setBlobUrls] = useState([]); @@ -50,9 +51,39 @@ export const useToolResources = () => { }, []); const extractZipFiles = useCallback(async (zipBlob: Blob): Promise => { - const zipFile = new File([zipBlob], 'temp.zip', { type: 'application/zip' }); - const extractionResult = await zipFileService.extractPdfFiles(zipFile); - return extractionResult.success ? extractionResult.extractedFiles : []; + try { + const zipFile = new File([zipBlob], 'temp.zip', { type: 'application/zip' }); + const extractionResult = await zipFileService.extractPdfFiles(zipFile); + return extractionResult.success ? extractionResult.extractedFiles : []; + } catch (error) { + console.error('useToolResources.extractZipFiles - Error:', error); + return []; + } + }, []); + + const extractAllZipFiles = useCallback(async (zipBlob: Blob): Promise => { + try { + const JSZip = (await import('jszip')).default; + const zip = new JSZip(); + + const arrayBuffer = await zipBlob.arrayBuffer(); + const zipContent = await zip.loadAsync(arrayBuffer); + + const extractedFiles: File[] = []; + + for (const [filename, file] of Object.entries(zipContent.files)) { + if (!file.dir) { + const content = await file.async('blob'); + const extractedFile = new File([content], filename, { type: 'application/pdf' }); + extractedFiles.push(extractedFile); + } + } + + return extractedFiles; + } catch (error) { + console.error('Error in extractAllZipFiles:', error); + return []; + } }, []); const createDownloadInfo = useCallback(async ( @@ -77,6 +108,7 @@ export const useToolResources = () => { generateThumbnails, createDownloadInfo, extractZipFiles, + extractAllZipFiles, cleanupBlobUrls, }; }; \ No newline at end of file