mirror of
https://github.com/langgenius/dify.git
synced 2026-09-06 01:04:49 +08:00
144 lines
6.1 KiB
Python
144 lines
6.1 KiB
Python
from flask import request
|
|
from flask_restx import Resource
|
|
from pydantic import BaseModel, Field
|
|
|
|
import services
|
|
from controllers.common import helpers
|
|
from controllers.common.errors import (
|
|
BlockedFileExtensionError,
|
|
FileTooLargeError,
|
|
RemoteFileAccessDeniedError,
|
|
RemoteFileInvalidResponseError,
|
|
RemoteFileInvalidUrlError,
|
|
RemoteFileNotFoundError,
|
|
RemoteFileUnavailableError,
|
|
RemoteFileUrlBlockedError,
|
|
UnsupportedFileTypeError,
|
|
)
|
|
from controllers.common.schema import JsonResponseWithStatus, register_response_schema_models, register_schema_models
|
|
from controllers.console import console_ns
|
|
from controllers.console.flask_admission import console_account_admission
|
|
from controllers.console.wraps import model_validate, with_current_user
|
|
from extensions.ext_application_services import application_services
|
|
from fields.file_fields import FileWithSignedUrl, RemoteFileInfo
|
|
from libs.helper import dump_response
|
|
from libs.login import login_required
|
|
from machinery.context import RequestContext
|
|
from models import Account
|
|
from services.remote_file_service import (
|
|
RemoteFileAccessDeniedError as RemoteFileAccessDeniedServiceError,
|
|
)
|
|
from services.remote_file_service import (
|
|
RemoteFileInvalidResponseError as RemoteFileInvalidResponseServiceError,
|
|
)
|
|
from services.remote_file_service import RemoteFileInvalidUrlError as RemoteFileInvalidUrlServiceError
|
|
from services.remote_file_service import RemoteFileNotFoundError as RemoteFileNotFoundServiceError
|
|
from services.remote_file_service import RemoteFileUnavailableError as RemoteFileUnavailableServiceError
|
|
from services.remote_file_service import RemoteFileUploadResult
|
|
from services.remote_file_service import RemoteFileUrlBlockedError as RemoteFileUrlBlockedServiceError
|
|
|
|
|
|
class RemoteFileUploadPayload(BaseModel):
|
|
url: str = Field(description="URL to fetch", json_schema_extra={"format": "uri"})
|
|
|
|
|
|
register_schema_models(console_ns, RemoteFileUploadPayload)
|
|
register_response_schema_models(console_ns, FileWithSignedUrl, RemoteFileInfo)
|
|
|
|
|
|
@console_ns.route("/remote-files/<path:url>")
|
|
class GetRemoteFileInfo(Resource):
|
|
@console_ns.doc(
|
|
responses={
|
|
400: "Invalid, blocked, or inaccessible remote file URL",
|
|
404: "Remote file not found",
|
|
502: "Remote file unavailable or returned an invalid response",
|
|
500: "Internal server error",
|
|
}
|
|
)
|
|
@console_ns.response(200, "Success", console_ns.models[RemoteFileInfo.__name__])
|
|
@console_account_admission()
|
|
def get(self, _request_context: RequestContext, url: str):
|
|
decoded_url = helpers.decode_remote_url(url, request.query_string)
|
|
try:
|
|
file_info = application_services().remote_files.fetch_info(url=decoded_url)
|
|
except RemoteFileInvalidUrlServiceError as error:
|
|
raise RemoteFileInvalidUrlError from error
|
|
except RemoteFileUrlBlockedServiceError as error:
|
|
raise RemoteFileUrlBlockedError from error
|
|
except RemoteFileNotFoundServiceError as error:
|
|
raise RemoteFileNotFoundError from error
|
|
except RemoteFileAccessDeniedServiceError as error:
|
|
raise RemoteFileAccessDeniedError from error
|
|
except RemoteFileUnavailableServiceError as error:
|
|
raise RemoteFileUnavailableError from error
|
|
except RemoteFileInvalidResponseServiceError as error:
|
|
raise RemoteFileInvalidResponseError from error
|
|
|
|
return dump_response(
|
|
RemoteFileInfo,
|
|
{
|
|
"file_type": file_info.content_type,
|
|
"file_length": file_info.content_length if file_info.content_length is not None else 0,
|
|
},
|
|
)
|
|
|
|
|
|
def upload_remote_file(
|
|
*,
|
|
url: str,
|
|
current_user: Account,
|
|
resource_tenant_id: str | None = None,
|
|
) -> RemoteFileUploadResult:
|
|
"""Fetch a remote file and persist it under the requested tenant."""
|
|
try:
|
|
return application_services().remote_files.upload_from_url(
|
|
url=url,
|
|
user=current_user,
|
|
tenant_id=resource_tenant_id,
|
|
)
|
|
except RemoteFileInvalidUrlServiceError as error:
|
|
raise RemoteFileInvalidUrlError from error
|
|
except RemoteFileUrlBlockedServiceError as error:
|
|
raise RemoteFileUrlBlockedError from error
|
|
except RemoteFileNotFoundServiceError as error:
|
|
raise RemoteFileNotFoundError from error
|
|
except RemoteFileAccessDeniedServiceError as error:
|
|
raise RemoteFileAccessDeniedError from error
|
|
except RemoteFileUnavailableServiceError as error:
|
|
raise RemoteFileUnavailableError from error
|
|
except RemoteFileInvalidResponseServiceError as error:
|
|
raise RemoteFileInvalidResponseError from error
|
|
except services.errors.file.FileTooLargeError as error:
|
|
raise FileTooLargeError(error.description or "File size exceeded.") from error
|
|
except services.errors.file.UnsupportedFileTypeError as error:
|
|
raise UnsupportedFileTypeError from error
|
|
except services.errors.file.BlockedFileExtensionError as error:
|
|
raise BlockedFileExtensionError(error.description) from error
|
|
|
|
|
|
@console_ns.route("/remote-files/upload")
|
|
class RemoteFileUpload(Resource):
|
|
@console_ns.doc(
|
|
responses={
|
|
400: "Invalid, blocked, or inaccessible remote file URL",
|
|
404: "Remote file not found",
|
|
413: "File too large",
|
|
415: "Unsupported file type",
|
|
422: "Request payload validation failed",
|
|
502: "Remote file unavailable or returned an invalid response",
|
|
500: "Internal server error",
|
|
}
|
|
)
|
|
@console_ns.expect(console_ns.models[RemoteFileUploadPayload.__name__])
|
|
@console_ns.response(201, "File uploaded successfully", console_ns.models[FileWithSignedUrl.__name__])
|
|
@login_required
|
|
@with_current_user
|
|
@model_validate(RemoteFileUploadPayload)
|
|
def post(self, payload: RemoteFileUploadPayload, current_user: Account) -> JsonResponseWithStatus:
|
|
remote_file = upload_remote_file(
|
|
url=payload.url,
|
|
current_user=current_user,
|
|
)
|
|
return dump_response(FileWithSignedUrl, remote_file), 201
|