Files
bentopdf/src/js/logic/repair-pdf.ts
alam00000 9d0b68e18c Refactor and enhance type safety across various modules
- Updated function parameters and return types in `page-preview.ts`, `pdf-decrypt.ts`, and `pymupdf-loader.ts` for improved type safety.
- Introduced type definitions for `CpdfInstance`, `PyMuPDFInstance`, and other related types to ensure better type checking.
- Enhanced error handling in `sanitize.ts` by creating a utility function for error messages.
- Removed unnecessary type assertions and improved type inference in `editor.ts`, `serialization.ts`, and `tools.test.ts`.
- Added type definitions for markdown-it plugins to improve compatibility and type safety.
- Enforced stricter TypeScript settings by enabling `noImplicitAny` in `tsconfig.json`.
- Cleaned up test files by refining type assertions and ensuring consistency in type usage.
2026-03-31 17:59:49 +05:30

142 lines
3.9 KiB
TypeScript

import { showLoader, hideLoader, showAlert } from '../ui.js';
import {
downloadFile,
initializeQpdf,
readFileAsArrayBuffer,
} from '../utils/helpers.js';
import { state } from '../state.js';
import JSZip from 'jszip';
import { deduplicateFileName } from '../utils/deduplicate-filename.js';
import { batchDecryptIfNeeded } from '../utils/password-prompt.js';
import type { QpdfInstanceExtended } from '@/types';
export async function repairPdfFile(file: File): Promise<Uint8Array | null> {
const inputPath = '/input.pdf';
const outputPath = '/repaired_form.pdf';
let qpdf: QpdfInstanceExtended;
try {
qpdf = await initializeQpdf();
const fileBuffer = await readFileAsArrayBuffer(file);
const uint8Array = new Uint8Array(fileBuffer as ArrayBuffer);
qpdf.FS.writeFile(inputPath, uint8Array);
const args = [inputPath, '--decrypt', outputPath];
try {
qpdf.callMain(args);
} catch (e) {
console.warn(`QPDF execution warning for ${file.name}:`, e);
}
let repairedData: Uint8Array | null = null;
try {
repairedData = qpdf.FS.readFile(outputPath, { encoding: 'binary' });
} catch (e) {
console.warn(`Failed to read output for ${file.name}:`, e);
}
try {
try {
qpdf.FS.unlink(inputPath);
} catch (e) {
console.warn(e);
}
try {
qpdf.FS.unlink(outputPath);
} catch (e) {
console.warn(e);
}
} catch (cleanupError) {
console.warn('Cleanup error:', cleanupError);
}
return repairedData;
} catch (error) {
console.error(`Error repairing ${file.name}:`, error);
return null;
}
}
export async function repairPdf() {
if (state.files.length === 0) {
showAlert('No Files', 'Please select one or more PDF files.');
return;
}
const successfulRepairs: { name: string; data: Uint8Array }[] = [];
const failedRepairs: string[] = [];
try {
const decryptedFiles = await batchDecryptIfNeeded(state.files);
showLoader('Initializing repair engine...');
state.files = decryptedFiles;
for (let i = 0; i < state.files.length; i++) {
const file = state.files[i];
showLoader(`Repairing ${file.name} (${i + 1}/${state.files.length})...`);
const repairedData = await repairPdfFile(file);
if (repairedData && repairedData.length > 0) {
successfulRepairs.push({
name: `repaired-${file.name}`,
data: repairedData,
});
} else {
failedRepairs.push(file.name);
}
}
hideLoader();
if (successfulRepairs.length === 0) {
showAlert(
'Repair Failed',
'Unable to repair any of the uploaded PDF files.'
);
return;
}
if (failedRepairs.length > 0) {
const failedList = failedRepairs.join(', ');
showAlert(
'Partial Success',
`Repaired ${successfulRepairs.length} file(s). Failed to repair: ${failedList}`
);
}
if (successfulRepairs.length === 1) {
const file = successfulRepairs[0];
const blob = new Blob([new Uint8Array(file.data)], {
type: 'application/pdf',
});
downloadFile(blob, file.name);
} else {
showLoader('Creating ZIP archive...');
const zip = new JSZip();
const usedNames = new Set<string>();
successfulRepairs.forEach((file) => {
const zipEntryName = deduplicateFileName(file.name, usedNames);
zip.file(zipEntryName, file.data);
});
const zipBlob = await zip.generateAsync({ type: 'blob' });
downloadFile(zipBlob, 'repaired_pdfs.zip');
hideLoader();
}
if (failedRepairs.length === 0) {
showAlert('Success', 'All files repaired successfully!');
}
} catch (error: unknown) {
console.error('Critical error during repair:', error);
hideLoader();
showAlert(
'Error',
'An unexpected error occurred during the repair process.'
);
}
}