Skip to content

Commit

Permalink
feat: pdf file preview (windmill-labs#4753)
Browse files Browse the repository at this point in the history
also fixes s3 missing content-length header
  • Loading branch information
HugoCasa authored Nov 19, 2024
1 parent 2fd80f7 commit b3a7cb0
Show file tree
Hide file tree
Showing 7 changed files with 421 additions and 289 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ frontend/src/routes/test.svelte
CaddyfileRemoteMalo
*.swp
**/.idea/
.direnv
.direnv
.vscode
3 changes: 0 additions & 3 deletions .vscode/settings.json

This file was deleted.

21 changes: 18 additions & 3 deletions backend/windmill-common/src/s3_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ use object_store::azure::MicrosoftAzureBuilder;
use object_store::ObjectStore;
#[cfg(feature = "parquet")]
use object_store::{aws::AmazonS3Builder, ClientOptions};
#[cfg(feature = "parquet")]
use reqwest::header::HeaderMap;
use serde::{Deserialize, Serialize};
#[cfg(feature = "parquet")]
use std::sync::Arc;
Expand Down Expand Up @@ -251,9 +253,15 @@ pub async fn build_s3_client(s3_resource_ref: &S3Resource) -> error::Result<Arc<
s3_resource.path_style,
s3_resource.bucket.clone(),
);

let mut store_builder = AmazonS3Builder::new()
.with_client_options(ClientOptions::new().with_timeout_disabled()) // TODO: make it configurable maybe
.with_client_options(
ClientOptions::new()
.with_timeout_disabled()
.with_default_headers(HeaderMap::from_iter(vec![(
"Accept-Encoding".parse().unwrap(),
"".parse().unwrap(),
)])),
) // TODO: make it configurable maybe
.with_region(s3_resource.region)
.with_bucket_name(s3_resource.bucket)
.with_endpoint(endpoint);
Expand Down Expand Up @@ -306,7 +314,14 @@ fn build_azure_blob_client(
let blob_resource = azure_blob_resource_ref.clone();

let mut store_builder = MicrosoftAzureBuilder::new()
.with_client_options(ClientOptions::new().with_timeout_disabled()) // TODO: make it configurable maybe
.with_client_options(
ClientOptions::new()
.with_timeout_disabled()
.with_default_headers(HeaderMap::from_iter(vec![(
"Accept-Encoding".parse().unwrap(),
"".parse().unwrap(),
)])),
) // TODO: make it configurable maybe
.with_account(blob_resource.account_name)
.with_container_name(blob_resource.container_name);

Expand Down
27 changes: 27 additions & 0 deletions frontend/src/lib/components/DisplayResult.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import { convertJsonToCsv } from './table/tableUtils'
import Tooltip from './Tooltip.svelte'
import HighlightTheme from './HighlightTheme.svelte'
import PdfViewer from './display/PdfViewer.svelte'
export let result: any
export let requireHtmlApproval = false
Expand Down Expand Up @@ -71,6 +72,7 @@
| 'markdown'
| 'map'
| 'nondisplayable'
| 'pdf'
| undefined
$: resultKind = inferResultKind(result)
Expand Down Expand Up @@ -199,6 +201,8 @@
return 'html'
} else if (keys.length == 1 && keys[0] === 'map') {
return 'map'
} else if (keys.length == 1 && keys[0] === 'pdf') {
return 'pdf'
} else if (keys.length == 1 && keys[0] === 'file') {
return 'file'
} else if (
Expand Down Expand Up @@ -528,6 +532,13 @@
src="data:image/gif;base64,{contentOrRootString(result.gif)}"
/>
</div>
{:else if !forceJson && resultKind === 'pdf'}
<div class="h-96 mt-2">
<PdfViewer
allowFullscreen
source="data:application/pdf;base64,{contentOrRootString(result.pdf)}"
/>
</div>
{:else if !forceJson && resultKind === 'plain'}<div class="h-full text-2xs"
><pre>{typeof result === 'string' ? result : result?.['result']}</pre>{#if !noControls}
<div class="flex">
Expand Down Expand Up @@ -667,6 +678,14 @@
(result.storage ? `&storage=${result.storage}` : '')}
/>
</div>
{:else if result?.s3?.endsWith('.pdf')}
<div class="h-96 mt-2">
<PdfViewer
allowFullscreen
source={`/api/w/${workspaceId}/job_helpers/load_image_preview?file_key=${result.s3}` +
(result.storage ? `&storage=${result.storage}` : '')}
/>
</div>
{/if}
{/if}
</div>
Expand Down Expand Up @@ -735,6 +754,14 @@
>open image preview <ArrowDownFromLine />
</button>
{/if}
{:else if s3object?.s3?.endsWith('.pdf')}
<div class="h-96 mt-2">
<PdfViewer
allowFullscreen
source={`/api/w/${workspaceId}/job_helpers/load_image_preview?file_key=${s3object.s3}` +
(s3object.storage ? `&storage=${s3object.storage}` : '')}
/>
</div>
{/if}
{/each}
</div>
Expand Down
18 changes: 18 additions & 0 deletions frontend/src/lib/components/S3FilePicker.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import TableSimple from './TableSimple.svelte'
import ConfirmationModal from './common/confirmationModal/ConfirmationModal.svelte'
import FileUploadModal from './common/fileUpload/FileUploadModal.svelte'
import PdfViewer from './display/PdfViewer.svelte'
let deletionModalOpen = false
let fileDeletionInProgress = false
Expand Down Expand Up @@ -245,6 +246,16 @@
contentPreview: filePreviewContent,
contentType: filePreviewRaw.content_type
}
if (fileMetadata) {
fileMetadata.mimeType =
((fileKey.endsWith('.png') ||
fileKey.endsWith('.jpg') ||
fileKey.endsWith('.jpeg') ||
fileKey.endsWith('.webp')) &&
'Image') ||
(fileKey.endsWith('.pdf') && 'PDF') ||
filePreview.contentType
}
}
filePreviewLoading = false
fileInfoLoading = false
Expand Down Expand Up @@ -616,6 +627,13 @@
alt="S3 preview"
/>
</div>
{:else if fileMetadata?.fileKey.endsWith('.pdf')}
<div class="w-full h-[950px] border">
<PdfViewer
source={`/api/w/${$workspaceStore}/job_helpers/load_image_preview?file_key=${fileMetadata.fileKey}` +
(storage ? `&storage=${storage}` : '')}
/>
</div>
{:else if filePreviewLoading}
<div class="flex h-6 items-center text-tertiary mb-4">
<Loader2 size={12} class="animate-spin mr-1" /> File preview loading
Expand Down
Loading

0 comments on commit b3a7cb0

Please sign in to comment.