mirror of
https://github.com/langgenius/dify.git
synced 2026-07-31 17:29:37 +08:00
feat: make skill package upload size limit configurable (#39799)
This commit is contained in:
parent
48bb46a72b
commit
8cca3959ae
@ -436,6 +436,7 @@ UPLOAD_FILE_BATCH_LIMIT=5
|
||||
UPLOAD_IMAGE_FILE_SIZE_LIMIT=10
|
||||
UPLOAD_VIDEO_FILE_SIZE_LIMIT=100
|
||||
UPLOAD_AUDIO_FILE_SIZE_LIMIT=50
|
||||
UPLOAD_SKILL_FILE_SIZE_LIMIT=50
|
||||
|
||||
# Comma-separated list of file extensions blocked from upload for security reasons.
|
||||
# Extensions should be lowercase without dots (e.g., exe,bat,sh,dll).
|
||||
|
||||
@ -470,6 +470,11 @@ class FileUploadConfig(BaseSettings):
|
||||
default=50,
|
||||
)
|
||||
|
||||
UPLOAD_SKILL_FILE_SIZE_LIMIT: NonNegativeInt = Field(
|
||||
description="Maximum allowed Skill package size for uploads in megabytes",
|
||||
default=50,
|
||||
)
|
||||
|
||||
BATCH_UPLOAD_LIMIT: NonNegativeInt = Field(
|
||||
description="Maximum number of files allowed in a batch upload operation",
|
||||
default=20,
|
||||
|
||||
@ -107,6 +107,7 @@ class FileApi(Resource):
|
||||
image_file_size_limit=dify_config.UPLOAD_IMAGE_FILE_SIZE_LIMIT,
|
||||
video_file_size_limit=dify_config.UPLOAD_VIDEO_FILE_SIZE_LIMIT,
|
||||
audio_file_size_limit=dify_config.UPLOAD_AUDIO_FILE_SIZE_LIMIT,
|
||||
skill_file_size_limit=dify_config.UPLOAD_SKILL_FILE_SIZE_LIMIT,
|
||||
workflow_file_upload_limit=dify_config.WORKFLOW_FILE_UPLOAD_LIMIT,
|
||||
image_file_batch_limit=dify_config.IMAGE_FILE_BATCH_LIMIT,
|
||||
single_chunk_attachment_limit=dify_config.SINGLE_CHUNK_ATTACHMENT_LIMIT,
|
||||
|
||||
@ -15,6 +15,7 @@ class UploadConfig(ResponseModel):
|
||||
image_file_size_limit: int
|
||||
video_file_size_limit: int
|
||||
audio_file_size_limit: int
|
||||
skill_file_size_limit: int
|
||||
workflow_file_upload_limit: int
|
||||
image_file_batch_limit: int
|
||||
single_chunk_attachment_limit: int
|
||||
|
||||
@ -22989,6 +22989,7 @@ Payload for updating a snippet.
|
||||
| image_file_batch_limit | integer | | Yes |
|
||||
| image_file_size_limit | integer | | Yes |
|
||||
| single_chunk_attachment_limit | integer | | Yes |
|
||||
| skill_file_size_limit | integer | | Yes |
|
||||
| video_file_size_limit | integer | | Yes |
|
||||
| workflow_file_upload_limit | integer | | Yes |
|
||||
|
||||
|
||||
@ -26,8 +26,9 @@ import zlib
|
||||
import yaml
|
||||
from pydantic import BaseModel
|
||||
|
||||
from configs import dify_config
|
||||
|
||||
# Bounds — generous but finite so a hostile upload can't exhaust memory/disk.
|
||||
_MAX_ARCHIVE_BYTES = 50 * 1024 * 1024
|
||||
_MAX_UNCOMPRESSED_BYTES = 200 * 1024 * 1024
|
||||
_MAX_SKILL_MD_BYTES = 1 * 1024 * 1024
|
||||
_MAX_ENTRIES = 5000
|
||||
@ -127,7 +128,8 @@ class SkillPackageService:
|
||||
self._check_extension(filename)
|
||||
if not content:
|
||||
raise SkillPackageError("empty_archive", "skill archive is empty", status_code=400)
|
||||
if len(content) > _MAX_ARCHIVE_BYTES:
|
||||
max_archive_bytes = dify_config.UPLOAD_SKILL_FILE_SIZE_LIMIT * 1024 * 1024
|
||||
if len(content) > max_archive_bytes:
|
||||
raise SkillPackageError("archive_too_large", "skill archive exceeds size limit", status_code=400)
|
||||
|
||||
try:
|
||||
|
||||
@ -37,6 +37,7 @@ def test_file_upload_config_returns_console_limits(
|
||||
"image_file_size_limit": dify_config.UPLOAD_IMAGE_FILE_SIZE_LIMIT,
|
||||
"video_file_size_limit": dify_config.UPLOAD_VIDEO_FILE_SIZE_LIMIT,
|
||||
"audio_file_size_limit": dify_config.UPLOAD_AUDIO_FILE_SIZE_LIMIT,
|
||||
"skill_file_size_limit": dify_config.UPLOAD_SKILL_FILE_SIZE_LIMIT,
|
||||
"workflow_file_upload_limit": dify_config.WORKFLOW_FILE_UPLOAD_LIMIT,
|
||||
"image_file_batch_limit": dify_config.IMAGE_FILE_BATCH_LIMIT,
|
||||
"single_chunk_attachment_limit": dify_config.SINGLE_CHUNK_ATTACHMENT_LIMIT,
|
||||
|
||||
@ -5,6 +5,7 @@ import pytest
|
||||
from flask import Flask
|
||||
from werkzeug.exceptions import Forbidden
|
||||
|
||||
from configs import dify_config
|
||||
from constants import DOCUMENT_EXTENSIONS
|
||||
from controllers.common.errors import (
|
||||
BlockedFileExtensionError,
|
||||
@ -92,6 +93,7 @@ class TestFileApiGet:
|
||||
assert status == 200
|
||||
assert "file_size_limit" in data
|
||||
assert "batch_count_limit" in data
|
||||
assert data["skill_file_size_limit"] == dify_config.UPLOAD_SKILL_FILE_SIZE_LIMIT
|
||||
|
||||
|
||||
class TestFileApiPost:
|
||||
|
||||
@ -72,15 +72,17 @@ def test_remote_file_info_and_upload_config() -> None:
|
||||
image_file_size_limit=4,
|
||||
video_file_size_limit=5,
|
||||
audio_file_size_limit=6,
|
||||
workflow_file_upload_limit=7,
|
||||
image_file_batch_limit=8,
|
||||
single_chunk_attachment_limit=9,
|
||||
attachment_image_file_size_limit=10,
|
||||
skill_file_size_limit=7,
|
||||
workflow_file_upload_limit=8,
|
||||
image_file_batch_limit=9,
|
||||
single_chunk_attachment_limit=10,
|
||||
attachment_image_file_size_limit=11,
|
||||
)
|
||||
|
||||
dumped = config.model_dump(mode="json")
|
||||
assert dumped["file_upload_limit"] == 3
|
||||
assert dumped["attachment_image_file_size_limit"] == 10
|
||||
assert dumped["skill_file_size_limit"] == 7
|
||||
assert dumped["attachment_image_file_size_limit"] == 11
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
@ -210,10 +210,10 @@ def test_validate_and_normalize_rejects_archive_too_large_uncompressed(monkeypat
|
||||
|
||||
|
||||
def test_validate_and_normalize_rejects_archive_too_large_uploaded_bytes(monkeypatch: pytest.MonkeyPatch):
|
||||
monkeypatch.setattr(skill_package_service_module, "_MAX_ARCHIVE_BYTES", 8)
|
||||
monkeypatch.setattr(skill_package_service_module.dify_config, "UPLOAD_SKILL_FILE_SIZE_LIMIT", 1)
|
||||
|
||||
with pytest.raises(SkillPackageError) as exc_info:
|
||||
SkillPackageService().validate_and_normalize(content=b"x" * 9, filename="skill.zip")
|
||||
SkillPackageService().validate_and_normalize(content=b"x" * (1024 * 1024 + 1), filename="skill.zip")
|
||||
assert exc_info.value.code == "archive_too_large"
|
||||
|
||||
|
||||
|
||||
@ -60,6 +60,7 @@ MULTIMODAL_SEND_FORMAT=base64
|
||||
UPLOAD_IMAGE_FILE_SIZE_LIMIT=10
|
||||
UPLOAD_VIDEO_FILE_SIZE_LIMIT=100
|
||||
UPLOAD_AUDIO_FILE_SIZE_LIMIT=50
|
||||
UPLOAD_SKILL_FILE_SIZE_LIMIT=50
|
||||
API_SENTRY_DSN=
|
||||
API_SENTRY_TRACES_SAMPLE_RATE=1.0
|
||||
API_SENTRY_PROFILES_SAMPLE_RATE=1.0
|
||||
|
||||
@ -17,6 +17,7 @@ export type UploadConfig = {
|
||||
image_file_batch_limit: number
|
||||
image_file_size_limit: number
|
||||
single_chunk_attachment_limit: number
|
||||
skill_file_size_limit: number
|
||||
video_file_size_limit: number
|
||||
workflow_file_upload_limit: number
|
||||
}
|
||||
|
||||
@ -21,6 +21,7 @@ export const zUploadConfig = z.object({
|
||||
image_file_batch_limit: z.int(),
|
||||
image_file_size_limit: z.int(),
|
||||
single_chunk_attachment_limit: z.int(),
|
||||
skill_file_size_limit: z.int(),
|
||||
video_file_size_limit: z.int(),
|
||||
workflow_file_upload_limit: z.int(),
|
||||
})
|
||||
|
||||
Loading…
Reference in New Issue
Block a user