Browse Source

Merge pull request #10415 from labanzu/better-pdf-preview

feat: better pdf preview
Timothy Jaeryang Baek 2 tháng trước cách đây
mục cha
commit
0994a07874

+ 16 - 9
backend/open_webui/routers/files.py

@@ -225,17 +225,24 @@ async def get_file_content_by_id(id: str, user=Depends(get_verified_user)):
                 filename = file.meta.get("name", file.filename)
                 encoded_filename = quote(filename)  # RFC5987 encoding
 
+                content_type = file.meta.get("content_type")
+                filename = file.meta.get("name", file.filename)
+                encoded_filename = quote(filename)
                 headers = {}
-                if file.meta.get("content_type") not in [
-                    "application/pdf",
-                    "text/plain",
-                ]:
-                    headers = {
-                        **headers,
-                        "Content-Disposition": f"attachment; filename*=UTF-8''{encoded_filename}",
-                    }
 
-                return FileResponse(file_path, headers=headers)
+                if content_type == "application/pdf" or filename.lower().endswith(
+                    ".pdf"
+                ):
+                    headers["Content-Disposition"] = (
+                        f"inline; filename*=UTF-8''{encoded_filename}"
+                    )
+                    content_type = "application/pdf"
+                elif content_type != "text/plain":
+                    headers["Content-Disposition"] = (
+                        f"attachment; filename*=UTF-8''{encoded_filename}"
+                    )
+
+                return FileResponse(file_path, headers=headers, media_type=content_type)
 
             else:
                 raise HTTPException(

+ 21 - 6
src/lib/components/common/FileItemModal.svelte

@@ -1,6 +1,7 @@
 <script lang="ts">
 	import { getContext, onMount } from 'svelte';
 	import { formatFileSize, getLineCount } from '$lib/utils';
+	import { WEBUI_API_BASE_URL } from '$lib/constants';
 
 	const i18n = getContext('i18n');
 
@@ -12,14 +13,14 @@
 
 	export let item;
 	export let show = false;
-
 	export let edit = false;
 
 	let enableFullContent = false;
+	$: isPDF = item?.meta?.content_type === 'application/pdf' ||
+	          (item?.name && item?.name.toLowerCase().endsWith('.pdf'));
 
 	onMount(() => {
 		console.log(item);
-
 		if (item?.context === 'full') {
 			enableFullContent = true;
 		}
@@ -33,9 +34,13 @@
 				<div>
 					<div class=" font-medium text-lg dark:text-gray-100">
 						<a
-							href={item.url ? (item.type === 'file' ? `${item.url}/content` : `${item.url}`) : '#'}
-							target="_blank"
+							href="#"
 							class="hover:underline line-clamp-1"
+							on:click|preventDefault={() => {
+								if (!isPDF && item.url) {
+									window.open(item.type === 'file' ? `${item.url}/content` : `${item.url}`, '_blank');
+								}
+							}}
 						>
 							{item?.name ?? 'File'}
 						</a>
@@ -101,8 +106,18 @@
 			</div>
 		</div>
 
-		<div class="max-h-96 overflow-scroll scrollbar-hidden text-xs whitespace-pre-wrap">
-			{item?.file?.data?.content ?? 'No content'}
+		<div class="max-h-[75vh] overflow-auto">
+			{#if isPDF}
+				<iframe
+					title={item?.name}
+					src={`${WEBUI_API_BASE_URL}/files/${item.id}/content`}
+					class="w-full h-[70vh] border-0 rounded-lg mt-4"
+				/>
+			{:else}
+				<div class="max-h-96 overflow-scroll scrollbar-hidden text-xs whitespace-pre-wrap">
+					{item?.file?.data?.content ?? 'No content'}
+				</div>
+			{/if}
 		</div>
 	</div>
 </Modal>

+ 1 - 4
src/lib/components/common/Modal.svelte

@@ -6,7 +6,6 @@
 
 	export let show = true;
 	export let size = 'md';
-
 	export let containerClassName = 'p-3';
 	export let className = 'bg-gray-50 dark:bg-gray-900 rounded-2xl';
 
@@ -74,9 +73,7 @@
 		}}
 	>
 		<div
-			class=" m-auto max-w-full {sizeToWidth(size)} {size !== 'full'
-				? 'mx-2'
-				: ''} shadow-3xl min-h-fit scrollbar-hidden {className}"
+			class="m-auto max-w-full {sizeToWidth(size)} {size !== 'full' ? 'mx-2' : ''} shadow-3xl min-h-fit scrollbar-hidden {className}"
 			in:flyAndScale
 			on:mousedown={(e) => {
 				e.stopPropagation();