First PDF attempt

This commit is contained in:
2025-05-01 19:35:05 +02:00
parent fe5baba610
commit 27f6f33f47
4 changed files with 656 additions and 13 deletions

View File

@ -47,4 +47,16 @@ export class FileApi {
`/file/${file.id}/download${forceDownload ? "?download=true" : ""}`
);
}
/**
* Download uploaded file
*/
static async DownloadUploadedFile(file: UploadedFile): Promise<Blob> {
return (
await APIClient.exec({
method: "GET",
uri: `/file/${file.id}/download`,
})
).data;
}
}

View File

@ -1,3 +1,4 @@
import CloudDownloadIcon from "@mui/icons-material/CloudDownload";
import {
Button,
Dialog,
@ -6,9 +7,17 @@ import {
Paper,
Typography,
} from "@mui/material";
import { FileApi, UploadedFile } from "../api/FileApi";
import { filesize } from "filesize";
import CloudDownloadIcon from "@mui/icons-material/CloudDownload";
import { pdfjs } from "react-pdf";
import { FileApi, UploadedFile } from "../api/FileApi";
import React from "react";
import { Document, Page } from "react-pdf";
import { AsyncWidget } from "../widgets/AsyncWidget";
pdfjs.GlobalWorkerOptions.workerSrc = new URL(
"pdfjs-dist/build/pdf.worker.min.mjs",
import.meta.url
).toString();
export function FileViewerDialog(p: {
open: boolean;
@ -22,11 +31,9 @@ export function FileViewerDialog(p: {
{p.file.file_name} ({filesize(p.file.file_size)})
</DialogTitle>
<FileViewer
fileName={p.file.file_name}
fileSize={p.file.file_size}
url={FileApi.DownloadURL(p.file)}
downloadUrl={FileApi.DownloadURL(p.file, true)}
mimetype={p.file.mime_type}
{...p.file}
/>
<DialogActions>
<Button onClick={p.onClose}>Close</Button>
@ -35,18 +42,17 @@ export function FileViewerDialog(p: {
);
}
interface ViewerProps {
fileName: string;
fileSize: number;
type ViewerProps = {
url: string;
downloadUrl: string;
mimetype: string;
}
} & UploadedFile;
function FileViewer(p: ViewerProps): React.ReactElement {
// Image
if (p.mimetype.startsWith("image/"))
return <ImageViewer {...p} />; // Default viewer
if (p.mime_type.startsWith("image/")) return <ImageViewer {...p} />;
// PDF
else if (p.mime_type === "application/pdf") return <PDFViewer {...p} />;
// Default viewer
else return <DefaultViewer {...p} />;
}
@ -54,6 +60,39 @@ function ImageViewer(p: ViewerProps): React.ReactElement {
return <img src={p.url} />;
}
function PDFViewer(p: ViewerProps): React.ReactElement {
const [pdfUrl, setPdfUrl] = React.useState<string | undefined>();
const [numPages, setNumPages] = React.useState<number>();
const [pageNumber, setPageNumber] = React.useState<number>(1);
const load = async () => {
const blob = await FileApi.DownloadUploadedFile(p);
setPdfUrl(URL.createObjectURL(blob));
};
function onDocumentLoadSuccess({ numPages }: { numPages: number }): void {
setNumPages(numPages);
}
return (
<AsyncWidget
loadKey={p.id}
load={load}
errMsg="Failed to load PDF!"
build={() => (
<div>
<Document file={pdfUrl} onLoadSuccess={onDocumentLoadSuccess}>
<Page pageNumber={pageNumber} />
</Document>
<p>
Page {pageNumber} of {numPages}
</p>
</div>
)}
/>
);
}
function DefaultViewer(p: ViewerProps): React.ReactElement {
return (
<Paper
@ -71,7 +110,7 @@ function DefaultViewer(p: ViewerProps): React.ReactElement {
<CloudDownloadIcon fontSize="large" />
</Typography>
<Typography variant="caption" gutterBottom>
{filesize(p.fileSize)}
{filesize(p.file_size)}
</Typography>
<a href={p.downloadUrl} target="_blank" referrerPolicy="no-referrer">
<Button variant="outlined">Download</Button>