fix(api): allow PDF extraction from URLs without an upload file (#41950)

This commit is contained in:
Harsh Kashyap 2026-09-08 11:01:52 +00:00 committed by GitHub
parent e34b2f9045
commit fc062bfc6d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 43 additions and 6 deletions

View File

@ -147,9 +147,11 @@ class ExtractProcessor:
upload_file.id,
)
elif file_extension == ".pdf":
assert upload_file is not None
extractor = PdfExtractor(
file_path, upload_file.tenant_id, upload_file.created_by, session=session
file_path,
upload_file.tenant_id if upload_file else None,
upload_file.created_by if upload_file else None,
session=session,
)
elif file_extension in {".md", ".markdown", ".mdx"}:
extractor = (
@ -195,9 +197,11 @@ class ExtractProcessor:
upload_file.id,
)
elif file_extension == ".pdf":
assert upload_file is not None
extractor = PdfExtractor(
file_path, upload_file.tenant_id, upload_file.created_by, session=session
file_path,
upload_file.tenant_id if upload_file else None,
upload_file.created_by if upload_file else None,
session=session,
)
elif file_extension in {".md", ".markdown", ".mdx"}:
extractor = MarkdownExtractor(file_path, autodetect_encoding=True)

View File

@ -55,8 +55,8 @@ class PdfExtractor(BaseExtractor):
def __init__(
self,
file_path: str,
tenant_id: str,
user_id: str,
tenant_id: str | None = None,
user_id: str | None = None,
file_cache_key: str | None = None,
*,
session: Session | None = None,
@ -127,6 +127,12 @@ class PdfExtractor(BaseExtractor):
Returns:
Markdown string containing links to the extracted images.
"""
if not self._tenant_id or not self._user_id:
# No tenant context (e.g. file loaded from a URL rather than an
# uploaded file): extracted images cannot be persisted, so skip
# image extraction and return text only.
return ""
image_content = []
upload_files = []
base_url = dify_config.FILES_URL

View File

@ -152,6 +152,21 @@ class TestExtractProcessorLoaders:
assert text == content
def test_load_from_url_extracts_pdf_without_upload_file(self, monkeypatch: pytest.MonkeyPatch):
response = SimpleNamespace(headers={"Content-Type": "application/pdf"}, content=b"%PDF-1.1 body")
monkeypatch.setattr(processor_module.remote_fetcher, "make_request", lambda *args, **kwargs: response)
factory = _patch_all_extractors(monkeypatch)
apply_config_overrides(monkeypatch, ETL_TYPE="dify")
text = ExtractProcessor.load_from_url("https://example.com/report", return_text=True)
assert text == "extracted-by-PdfExtractor"
name, args, kwargs = factory.calls[-1]
assert name == "PdfExtractor"
# no upload_file for URL-loaded files: tenant/user context must be None
assert args[1] is None
assert args[2] is None
class TestExtractProcessorFileRouting:
@pytest.fixture(autouse=True)

View File

@ -196,3 +196,15 @@ def test_extract_images_failures(mock_dependencies: _Dependencies):
assert upload_file is not None
assert f"![image](http://files.local/files/{upload_file.id}/file-preview)" in result
assert mock_dependencies.storage.saves == [(upload_file.key, jpeg_bytes)]
def test_extract_images_skipped_without_tenant_context():
"""PDFs loaded from a URL have no tenant/user context; image extraction must be skipped."""
mock_page = MagicMock()
extractor = pe.PdfExtractor(file_path="test.pdf")
result = extractor._extract_images(mock_page)
assert result == ""
mock_page.get_objects.assert_not_called()