Add PDF first-page thumbnails via pdftoppm
Generated at upload time, stored alongside the PDF in data/pdfs/. Shown in the file picker (48px) and component detail view (80px). Gracefully skipped if pdftoppm is unavailable. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
22
server.mjs
22
server.mjs
@@ -5,6 +5,7 @@ import express from 'express';
|
||||
import multer from 'multer';
|
||||
import { unlinkSync, mkdirSync } from 'node:fs';
|
||||
import { extname, join } from 'node:path';
|
||||
import { execFileSync } from 'node:child_process';
|
||||
import sharp from 'sharp';
|
||||
import { generate_id } from './lib/ids.mjs';
|
||||
import { compute_cell_size, process_grid_image } from './lib/grid-image.mjs';
|
||||
@@ -62,6 +63,20 @@ function remove_image_file(img_id) {
|
||||
try { unlinkSync(join('./data/images', img_id)); } catch {}
|
||||
}
|
||||
|
||||
function generate_pdf_thumb(pdf_path, thumb_prefix) {
|
||||
// Returns thumb filename (id-thumb.png) on success, null if pdftoppm unavailable.
|
||||
try {
|
||||
execFileSync('pdftoppm', [
|
||||
'-png', '-singlefile', '-scale-to', '512',
|
||||
'-f', '1', '-l', '1',
|
||||
pdf_path, thumb_prefix,
|
||||
]);
|
||||
return thumb_prefix.split('/').pop() + '.png';
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Field definitions
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -491,12 +506,16 @@ app.post('/api/pdfs', pdf_upload.single('file'), (req, res) => {
|
||||
try { unlinkSync(join('./data/pdfs', req.file.filename)); } catch {}
|
||||
return fail(res, 'a file with that name already exists');
|
||||
}
|
||||
const id = generate_id();
|
||||
const thumb_prefix = join('./data/pdfs', id + '-thumb');
|
||||
const thumb_file = generate_pdf_thumb(join('./data/pdfs', req.file.filename), thumb_prefix);
|
||||
const pdf = {
|
||||
id: generate_id(),
|
||||
id,
|
||||
filename: req.file.filename,
|
||||
display_name,
|
||||
original_name: req.file.originalname,
|
||||
size: req.file.size,
|
||||
thumb_filename: thumb_file,
|
||||
uploaded_at: Date.now(),
|
||||
};
|
||||
set_pdf(pdf);
|
||||
@@ -520,6 +539,7 @@ app.delete('/api/pdfs/:id', (req, res) => {
|
||||
const pdf = get_pdf(req.params.id);
|
||||
if (!pdf) return fail(res, 'not found', 404);
|
||||
try { unlinkSync(join('./data/pdfs', pdf.filename)); } catch {}
|
||||
if (pdf.thumb_filename) { try { unlinkSync(join('./data/pdfs', pdf.thumb_filename)); } catch {} }
|
||||
delete_pdf(req.params.id);
|
||||
ok(res);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user