fix: pdf render (#731)

This commit is contained in:
Wendong-Fan 2025-11-21 01:46:57 +08:00 committed by GitHub
commit 2bf89fd27d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 78 additions and 9 deletions

View file

@ -89,6 +89,21 @@ app.commandLine.appendSwitch('max_old_space_size', '4096');
app.commandLine.appendSwitch('enable-features', 'MemoryPressureReduction');
app.commandLine.appendSwitch('renderer-process-limit', '8');
// ==================== protocol privileges ====================
// Register custom protocol privileges before app ready
protocol.registerSchemesAsPrivileged([
{
scheme: 'localfile',
privileges: {
standard: true,
secure: true,
supportFetchAPI: true,
corsEnabled: false,
bypassCSP: false,
},
},
]);
// ==================== app config ====================
process.env.APP_ROOT = MAIN_DIST;
process.env.VITE_PUBLIC = VITE_PUBLIC;
@ -1577,12 +1592,24 @@ app.whenReady().then(async () => {
});
// ==================== protocol handle ====================
protocol.handle('localfile', async (request) => {
// Register protocol handler for both default session and main window session
const protocolHandler = async (request: Request) => {
const url = decodeURIComponent(request.url.replace('localfile://', ''));
const filePath = path.normalize(url);
log.info(`[PROTOCOL] Handling localfile request: ${request.url}`);
log.info(`[PROTOCOL] Decoded path: ${filePath}`);
try {
// Check if file exists
const fileExists = await fsp.access(filePath).then(() => true).catch(() => false);
if (!fileExists) {
log.error(`[PROTOCOL] File not found: ${filePath}`);
return new Response('File Not Found', { status: 404 });
}
const data = await fsp.readFile(filePath);
log.info(`[PROTOCOL] Successfully read file, size: ${data.length} bytes`);
// set correct Content-Type according to file extension
const ext = path.extname(filePath).toLowerCase();
@ -1596,17 +1623,46 @@ app.whenReady().then(async () => {
case '.htm':
contentType = 'text/html';
break;
case '.png':
contentType = 'image/png';
break;
case '.jpg':
case '.jpeg':
contentType = 'image/jpeg';
break;
case '.gif':
contentType = 'image/gif';
break;
case '.svg':
contentType = 'image/svg+xml';
break;
case '.webp':
contentType = 'image/webp';
break;
}
log.info(`[PROTOCOL] Returning file with Content-Type: ${contentType}`);
return new Response(new Uint8Array(data), {
headers: {
'Content-Type': contentType,
'Content-Length': data.length.toString(),
},
});
} catch (err) {
return new Response('Not Found', { status: 404 });
log.error(`[PROTOCOL] Error reading file: ${err}`);
return new Response('Internal Server Error', { status: 500 });
}
});
};
// Register on default session
protocol.handle('localfile', protocolHandler);
// Also register on main window session
const mainSession = session.fromPartition('persist:main_window');
mainSession.protocol.handle('localfile', protocolHandler);
log.info('[PROTOCOL] Registered localfile protocol on both default and main_window sessions');
// ==================== initialize app ====================
initializeApp();

View file

@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
http-equiv="Content-Security-Policy"
content="script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.amplitude.com; worker-src 'self' blob:; child-src 'self' blob:;frame-src 'self' localfile: blob:;"
content="script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.amplitude.com; worker-src 'self' blob:; child-src 'self' blob:;frame-src 'self' localfile: blob: data:;"
/>
<script src="https://cdn.amplitude.com/libs/analytics-browser-2.11.1-min.js.gz"></script><script src="https://cdn.amplitude.com/libs/plugin-session-replay-browser-1.8.0-min.js.gz"></script><script>window.amplitude.add(window.sessionReplay.plugin({sampleRate: 1}));window.amplitude.init('87ce6adbb14b24ffe1703d18bf405e40', {"autocapture":{"elementInteractions":true}});</script>
<title>Eigent</title>

View file

@ -183,7 +183,23 @@ export default function Folder({ data }: { data?: Agent }) {
setLoading(true);
console.log("file", JSON.parse(JSON.stringify(file)));
// all files call open-file interface, the backend handles download and parsing
// For PDF files, use data URL instead of custom protocol
if (file.type === "pdf") {
window.ipcRenderer
.invoke("read-file-dataurl", file.path)
.then((dataUrl: string) => {
setSelectedFile({ ...file, content: dataUrl });
chatStore.setSelectedFile(chatStore.activeTaskId as string, file);
setLoading(false);
})
.catch((error) => {
console.error("read-file-dataurl error:", error);
setLoading(false);
});
return;
}
// all other files call open-file interface, the backend handles download and parsing
window.ipcRenderer
.invoke("open-file", file.type, file.path, isShowSourceCode)
.then((res) => {
@ -539,10 +555,7 @@ export default function Folder({ data }: { data?: Agent }) {
</div>
) : selectedFile.type === "pdf" ? (
<iframe
src={
"localfile://" +
encodeURIComponent(selectedFile.content as string)
}
src={selectedFile.content as string}
className="w-full h-full border-0"
title={selectedFile.name}
/>