feat: add Service API file preview endpoint (#23534)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
@@ -6,6 +6,6 @@ bp = Blueprint("service_api", __name__, url_prefix="/v1")
|
||||
api = ExternalApi(bp)
|
||||
|
||||
from . import index
|
||||
from .app import annotation, app, audio, completion, conversation, file, message, site, workflow
|
||||
from .app import annotation, app, audio, completion, conversation, file, file_preview, message, site, workflow
|
||||
from .dataset import dataset, document, hit_testing, metadata, segment, upload_file
|
||||
from .workspace import models
|
||||
|
@@ -107,3 +107,15 @@ class UnsupportedFileTypeError(BaseHTTPException):
|
||||
error_code = "unsupported_file_type"
|
||||
description = "File type not allowed."
|
||||
code = 415
|
||||
|
||||
|
||||
class FileNotFoundError(BaseHTTPException):
|
||||
error_code = "file_not_found"
|
||||
description = "The requested file was not found."
|
||||
code = 404
|
||||
|
||||
|
||||
class FileAccessDeniedError(BaseHTTPException):
|
||||
error_code = "file_access_denied"
|
||||
description = "Access to the requested file is denied."
|
||||
code = 403
|
||||
|
186
api/controllers/service_api/app/file_preview.py
Normal file
186
api/controllers/service_api/app/file_preview.py
Normal file
@@ -0,0 +1,186 @@
|
||||
import logging
|
||||
from urllib.parse import quote
|
||||
|
||||
from flask import Response
|
||||
from flask_restful import Resource, reqparse
|
||||
|
||||
from controllers.service_api import api
|
||||
from controllers.service_api.app.error import (
|
||||
FileAccessDeniedError,
|
||||
FileNotFoundError,
|
||||
)
|
||||
from controllers.service_api.wraps import FetchUserArg, WhereisUserArg, validate_app_token
|
||||
from extensions.ext_database import db
|
||||
from extensions.ext_storage import storage
|
||||
from models.model import App, EndUser, Message, MessageFile, UploadFile
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class FilePreviewApi(Resource):
|
||||
"""
|
||||
Service API File Preview endpoint
|
||||
|
||||
Provides secure file preview/download functionality for external API users.
|
||||
Files can only be accessed if they belong to messages within the requesting app's context.
|
||||
"""
|
||||
|
||||
@validate_app_token(fetch_user_arg=FetchUserArg(fetch_from=WhereisUserArg.QUERY))
|
||||
def get(self, app_model: App, end_user: EndUser, file_id: str):
|
||||
"""
|
||||
Preview/Download a file that was uploaded via Service API
|
||||
|
||||
Args:
|
||||
app_model: The authenticated app model
|
||||
end_user: The authenticated end user (optional)
|
||||
file_id: UUID of the file to preview
|
||||
|
||||
Query Parameters:
|
||||
user: Optional user identifier
|
||||
as_attachment: Boolean, whether to download as attachment (default: false)
|
||||
|
||||
Returns:
|
||||
Stream response with file content
|
||||
|
||||
Raises:
|
||||
FileNotFoundError: File does not exist
|
||||
FileAccessDeniedError: File access denied (not owned by app)
|
||||
"""
|
||||
file_id = str(file_id)
|
||||
|
||||
# Parse query parameters
|
||||
parser = reqparse.RequestParser()
|
||||
parser.add_argument("as_attachment", type=bool, required=False, default=False, location="args")
|
||||
args = parser.parse_args()
|
||||
|
||||
# Validate file ownership and get file objects
|
||||
message_file, upload_file = self._validate_file_ownership(file_id, app_model.id)
|
||||
|
||||
# Get file content generator
|
||||
try:
|
||||
generator = storage.load(upload_file.key, stream=True)
|
||||
except Exception as e:
|
||||
raise FileNotFoundError(f"Failed to load file content: {str(e)}")
|
||||
|
||||
# Build response with appropriate headers
|
||||
response = self._build_file_response(generator, upload_file, args["as_attachment"])
|
||||
|
||||
return response
|
||||
|
||||
def _validate_file_ownership(self, file_id: str, app_id: str) -> tuple[MessageFile, UploadFile]:
|
||||
"""
|
||||
Validate that the file belongs to a message within the requesting app's context
|
||||
|
||||
Security validations performed:
|
||||
1. File exists in MessageFile table (was used in a conversation)
|
||||
2. Message belongs to the requesting app
|
||||
3. UploadFile record exists and is accessible
|
||||
4. File tenant matches app tenant (additional security layer)
|
||||
|
||||
Args:
|
||||
file_id: UUID of the file to validate
|
||||
app_id: UUID of the requesting app
|
||||
|
||||
Returns:
|
||||
Tuple of (MessageFile, UploadFile) if validation passes
|
||||
|
||||
Raises:
|
||||
FileNotFoundError: File or related records not found
|
||||
FileAccessDeniedError: File does not belong to the app's context
|
||||
"""
|
||||
try:
|
||||
# Input validation
|
||||
if not file_id or not app_id:
|
||||
raise FileAccessDeniedError("Invalid file or app identifier")
|
||||
|
||||
# First, find the MessageFile that references this upload file
|
||||
message_file = db.session.query(MessageFile).where(MessageFile.upload_file_id == file_id).first()
|
||||
|
||||
if not message_file:
|
||||
raise FileNotFoundError("File not found in message context")
|
||||
|
||||
# Get the message and verify it belongs to the requesting app
|
||||
message = (
|
||||
db.session.query(Message).where(Message.id == message_file.message_id, Message.app_id == app_id).first()
|
||||
)
|
||||
|
||||
if not message:
|
||||
raise FileAccessDeniedError("File access denied: not owned by requesting app")
|
||||
|
||||
# Get the actual upload file record
|
||||
upload_file = db.session.query(UploadFile).where(UploadFile.id == file_id).first()
|
||||
|
||||
if not upload_file:
|
||||
raise FileNotFoundError("Upload file record not found")
|
||||
|
||||
# Additional security: verify tenant isolation
|
||||
app = db.session.query(App).where(App.id == app_id).first()
|
||||
if app and upload_file.tenant_id != app.tenant_id:
|
||||
raise FileAccessDeniedError("File access denied: tenant mismatch")
|
||||
|
||||
return message_file, upload_file
|
||||
|
||||
except (FileNotFoundError, FileAccessDeniedError):
|
||||
# Re-raise our custom exceptions
|
||||
raise
|
||||
except Exception as e:
|
||||
# Log unexpected errors for debugging
|
||||
logger.exception(
|
||||
"Unexpected error during file ownership validation",
|
||||
extra={"file_id": file_id, "app_id": app_id, "error": str(e)},
|
||||
)
|
||||
raise FileAccessDeniedError("File access validation failed")
|
||||
|
||||
def _build_file_response(self, generator, upload_file: UploadFile, as_attachment: bool = False) -> Response:
|
||||
"""
|
||||
Build Flask Response object with appropriate headers for file streaming
|
||||
|
||||
Args:
|
||||
generator: File content generator from storage
|
||||
upload_file: UploadFile database record
|
||||
as_attachment: Whether to set Content-Disposition as attachment
|
||||
|
||||
Returns:
|
||||
Flask Response object with streaming file content
|
||||
"""
|
||||
response = Response(
|
||||
generator,
|
||||
mimetype=upload_file.mime_type,
|
||||
direct_passthrough=True,
|
||||
headers={},
|
||||
)
|
||||
|
||||
# Add Content-Length if known
|
||||
if upload_file.size and upload_file.size > 0:
|
||||
response.headers["Content-Length"] = str(upload_file.size)
|
||||
|
||||
# Add Accept-Ranges header for audio/video files to support seeking
|
||||
if upload_file.mime_type in [
|
||||
"audio/mpeg",
|
||||
"audio/wav",
|
||||
"audio/mp4",
|
||||
"audio/ogg",
|
||||
"audio/flac",
|
||||
"audio/aac",
|
||||
"video/mp4",
|
||||
"video/webm",
|
||||
"video/quicktime",
|
||||
"audio/x-m4a",
|
||||
]:
|
||||
response.headers["Accept-Ranges"] = "bytes"
|
||||
|
||||
# Set Content-Disposition for downloads
|
||||
if as_attachment and upload_file.name:
|
||||
encoded_filename = quote(upload_file.name)
|
||||
response.headers["Content-Disposition"] = f"attachment; filename*=UTF-8''{encoded_filename}"
|
||||
# Override content-type for downloads to force download
|
||||
response.headers["Content-Type"] = "application/octet-stream"
|
||||
|
||||
# Add caching headers for performance
|
||||
response.headers["Cache-Control"] = "public, max-age=3600" # Cache for 1 hour
|
||||
|
||||
return response
|
||||
|
||||
|
||||
# Register the API endpoint
|
||||
api.add_resource(FilePreviewApi, "/files/<uuid:file_id>/preview")
|
@@ -0,0 +1,336 @@
|
||||
"""
|
||||
Unit tests for Service API File Preview endpoint
|
||||
"""
|
||||
|
||||
import uuid
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from controllers.service_api.app.error import FileAccessDeniedError, FileNotFoundError
|
||||
from controllers.service_api.app.file_preview import FilePreviewApi
|
||||
from models.model import App, EndUser, Message, MessageFile, UploadFile
|
||||
|
||||
|
||||
class TestFilePreviewApi:
|
||||
"""Test suite for FilePreviewApi"""
|
||||
|
||||
@pytest.fixture
|
||||
def file_preview_api(self):
|
||||
"""Create FilePreviewApi instance for testing"""
|
||||
return FilePreviewApi()
|
||||
|
||||
@pytest.fixture
|
||||
def mock_app(self):
|
||||
"""Mock App model"""
|
||||
app = Mock(spec=App)
|
||||
app.id = str(uuid.uuid4())
|
||||
app.tenant_id = str(uuid.uuid4())
|
||||
return app
|
||||
|
||||
@pytest.fixture
|
||||
def mock_end_user(self):
|
||||
"""Mock EndUser model"""
|
||||
end_user = Mock(spec=EndUser)
|
||||
end_user.id = str(uuid.uuid4())
|
||||
return end_user
|
||||
|
||||
@pytest.fixture
|
||||
def mock_upload_file(self):
|
||||
"""Mock UploadFile model"""
|
||||
upload_file = Mock(spec=UploadFile)
|
||||
upload_file.id = str(uuid.uuid4())
|
||||
upload_file.name = "test_file.jpg"
|
||||
upload_file.mime_type = "image/jpeg"
|
||||
upload_file.size = 1024
|
||||
upload_file.key = "storage/key/test_file.jpg"
|
||||
upload_file.tenant_id = str(uuid.uuid4())
|
||||
return upload_file
|
||||
|
||||
@pytest.fixture
|
||||
def mock_message_file(self):
|
||||
"""Mock MessageFile model"""
|
||||
message_file = Mock(spec=MessageFile)
|
||||
message_file.id = str(uuid.uuid4())
|
||||
message_file.upload_file_id = str(uuid.uuid4())
|
||||
message_file.message_id = str(uuid.uuid4())
|
||||
return message_file
|
||||
|
||||
@pytest.fixture
|
||||
def mock_message(self):
|
||||
"""Mock Message model"""
|
||||
message = Mock(spec=Message)
|
||||
message.id = str(uuid.uuid4())
|
||||
message.app_id = str(uuid.uuid4())
|
||||
return message
|
||||
|
||||
def test_validate_file_ownership_success(
|
||||
self, file_preview_api, mock_app, mock_upload_file, mock_message_file, mock_message
|
||||
):
|
||||
"""Test successful file ownership validation"""
|
||||
file_id = str(uuid.uuid4())
|
||||
app_id = mock_app.id
|
||||
|
||||
# Set up the mocks
|
||||
mock_upload_file.tenant_id = mock_app.tenant_id
|
||||
mock_message.app_id = app_id
|
||||
mock_message_file.upload_file_id = file_id
|
||||
mock_message_file.message_id = mock_message.id
|
||||
|
||||
with patch("controllers.service_api.app.file_preview.db") as mock_db:
|
||||
# Mock database queries
|
||||
mock_db.session.query.return_value.where.return_value.first.side_effect = [
|
||||
mock_message_file, # MessageFile query
|
||||
mock_message, # Message query
|
||||
mock_upload_file, # UploadFile query
|
||||
mock_app, # App query for tenant validation
|
||||
]
|
||||
|
||||
# Execute the method
|
||||
result_message_file, result_upload_file = file_preview_api._validate_file_ownership(file_id, app_id)
|
||||
|
||||
# Assertions
|
||||
assert result_message_file == mock_message_file
|
||||
assert result_upload_file == mock_upload_file
|
||||
|
||||
def test_validate_file_ownership_file_not_found(self, file_preview_api):
|
||||
"""Test file ownership validation when MessageFile not found"""
|
||||
file_id = str(uuid.uuid4())
|
||||
app_id = str(uuid.uuid4())
|
||||
|
||||
with patch("controllers.service_api.app.file_preview.db") as mock_db:
|
||||
# Mock MessageFile not found
|
||||
mock_db.session.query.return_value.where.return_value.first.return_value = None
|
||||
|
||||
# Execute and assert exception
|
||||
with pytest.raises(FileNotFoundError) as exc_info:
|
||||
file_preview_api._validate_file_ownership(file_id, app_id)
|
||||
|
||||
assert "File not found in message context" in str(exc_info.value)
|
||||
|
||||
def test_validate_file_ownership_access_denied(self, file_preview_api, mock_message_file):
|
||||
"""Test file ownership validation when Message not owned by app"""
|
||||
file_id = str(uuid.uuid4())
|
||||
app_id = str(uuid.uuid4())
|
||||
|
||||
with patch("controllers.service_api.app.file_preview.db") as mock_db:
|
||||
# Mock MessageFile found but Message not owned by app
|
||||
mock_db.session.query.return_value.where.return_value.first.side_effect = [
|
||||
mock_message_file, # MessageFile query - found
|
||||
None, # Message query - not found (access denied)
|
||||
]
|
||||
|
||||
# Execute and assert exception
|
||||
with pytest.raises(FileAccessDeniedError) as exc_info:
|
||||
file_preview_api._validate_file_ownership(file_id, app_id)
|
||||
|
||||
assert "not owned by requesting app" in str(exc_info.value)
|
||||
|
||||
def test_validate_file_ownership_upload_file_not_found(self, file_preview_api, mock_message_file, mock_message):
|
||||
"""Test file ownership validation when UploadFile not found"""
|
||||
file_id = str(uuid.uuid4())
|
||||
app_id = str(uuid.uuid4())
|
||||
|
||||
with patch("controllers.service_api.app.file_preview.db") as mock_db:
|
||||
# Mock MessageFile and Message found but UploadFile not found
|
||||
mock_db.session.query.return_value.where.return_value.first.side_effect = [
|
||||
mock_message_file, # MessageFile query - found
|
||||
mock_message, # Message query - found
|
||||
None, # UploadFile query - not found
|
||||
]
|
||||
|
||||
# Execute and assert exception
|
||||
with pytest.raises(FileNotFoundError) as exc_info:
|
||||
file_preview_api._validate_file_ownership(file_id, app_id)
|
||||
|
||||
assert "Upload file record not found" in str(exc_info.value)
|
||||
|
||||
def test_validate_file_ownership_tenant_mismatch(
|
||||
self, file_preview_api, mock_app, mock_upload_file, mock_message_file, mock_message
|
||||
):
|
||||
"""Test file ownership validation with tenant mismatch"""
|
||||
file_id = str(uuid.uuid4())
|
||||
app_id = mock_app.id
|
||||
|
||||
# Set up tenant mismatch
|
||||
mock_upload_file.tenant_id = "different_tenant_id"
|
||||
mock_app.tenant_id = "app_tenant_id"
|
||||
mock_message.app_id = app_id
|
||||
mock_message_file.upload_file_id = file_id
|
||||
mock_message_file.message_id = mock_message.id
|
||||
|
||||
with patch("controllers.service_api.app.file_preview.db") as mock_db:
|
||||
# Mock database queries
|
||||
mock_db.session.query.return_value.where.return_value.first.side_effect = [
|
||||
mock_message_file, # MessageFile query
|
||||
mock_message, # Message query
|
||||
mock_upload_file, # UploadFile query
|
||||
mock_app, # App query for tenant validation
|
||||
]
|
||||
|
||||
# Execute and assert exception
|
||||
with pytest.raises(FileAccessDeniedError) as exc_info:
|
||||
file_preview_api._validate_file_ownership(file_id, app_id)
|
||||
|
||||
assert "tenant mismatch" in str(exc_info.value)
|
||||
|
||||
def test_validate_file_ownership_invalid_input(self, file_preview_api):
|
||||
"""Test file ownership validation with invalid input"""
|
||||
|
||||
# Test with empty file_id
|
||||
with pytest.raises(FileAccessDeniedError) as exc_info:
|
||||
file_preview_api._validate_file_ownership("", "app_id")
|
||||
assert "Invalid file or app identifier" in str(exc_info.value)
|
||||
|
||||
# Test with empty app_id
|
||||
with pytest.raises(FileAccessDeniedError) as exc_info:
|
||||
file_preview_api._validate_file_ownership("file_id", "")
|
||||
assert "Invalid file or app identifier" in str(exc_info.value)
|
||||
|
||||
def test_build_file_response_basic(self, file_preview_api, mock_upload_file):
|
||||
"""Test basic file response building"""
|
||||
mock_generator = Mock()
|
||||
|
||||
response = file_preview_api._build_file_response(mock_generator, mock_upload_file, False)
|
||||
|
||||
# Check response properties
|
||||
assert response.mimetype == mock_upload_file.mime_type
|
||||
assert response.direct_passthrough is True
|
||||
assert response.headers["Content-Length"] == str(mock_upload_file.size)
|
||||
assert "Cache-Control" in response.headers
|
||||
|
||||
def test_build_file_response_as_attachment(self, file_preview_api, mock_upload_file):
|
||||
"""Test file response building with attachment flag"""
|
||||
mock_generator = Mock()
|
||||
|
||||
response = file_preview_api._build_file_response(mock_generator, mock_upload_file, True)
|
||||
|
||||
# Check attachment-specific headers
|
||||
assert "attachment" in response.headers["Content-Disposition"]
|
||||
assert mock_upload_file.name in response.headers["Content-Disposition"]
|
||||
assert response.headers["Content-Type"] == "application/octet-stream"
|
||||
|
||||
def test_build_file_response_audio_video(self, file_preview_api, mock_upload_file):
|
||||
"""Test file response building for audio/video files"""
|
||||
mock_generator = Mock()
|
||||
mock_upload_file.mime_type = "video/mp4"
|
||||
|
||||
response = file_preview_api._build_file_response(mock_generator, mock_upload_file, False)
|
||||
|
||||
# Check Range support for media files
|
||||
assert response.headers["Accept-Ranges"] == "bytes"
|
||||
|
||||
def test_build_file_response_no_size(self, file_preview_api, mock_upload_file):
|
||||
"""Test file response building when size is unknown"""
|
||||
mock_generator = Mock()
|
||||
mock_upload_file.size = 0 # Unknown size
|
||||
|
||||
response = file_preview_api._build_file_response(mock_generator, mock_upload_file, False)
|
||||
|
||||
# Content-Length should not be set when size is unknown
|
||||
assert "Content-Length" not in response.headers
|
||||
|
||||
@patch("controllers.service_api.app.file_preview.storage")
|
||||
def test_get_method_integration(
|
||||
self, mock_storage, file_preview_api, mock_app, mock_end_user, mock_upload_file, mock_message_file, mock_message
|
||||
):
|
||||
"""Test the full GET method integration (without decorator)"""
|
||||
file_id = str(uuid.uuid4())
|
||||
app_id = mock_app.id
|
||||
|
||||
# Set up mocks
|
||||
mock_upload_file.tenant_id = mock_app.tenant_id
|
||||
mock_message.app_id = app_id
|
||||
mock_message_file.upload_file_id = file_id
|
||||
mock_message_file.message_id = mock_message.id
|
||||
|
||||
mock_generator = Mock()
|
||||
mock_storage.load.return_value = mock_generator
|
||||
|
||||
with patch("controllers.service_api.app.file_preview.db") as mock_db:
|
||||
# Mock database queries
|
||||
mock_db.session.query.return_value.where.return_value.first.side_effect = [
|
||||
mock_message_file, # MessageFile query
|
||||
mock_message, # Message query
|
||||
mock_upload_file, # UploadFile query
|
||||
mock_app, # App query for tenant validation
|
||||
]
|
||||
|
||||
with patch("controllers.service_api.app.file_preview.reqparse") as mock_reqparse:
|
||||
# Mock request parsing
|
||||
mock_parser = Mock()
|
||||
mock_parser.parse_args.return_value = {"as_attachment": False}
|
||||
mock_reqparse.RequestParser.return_value = mock_parser
|
||||
|
||||
# Test the core logic directly without Flask decorators
|
||||
# Validate file ownership
|
||||
result_message_file, result_upload_file = file_preview_api._validate_file_ownership(file_id, app_id)
|
||||
assert result_message_file == mock_message_file
|
||||
assert result_upload_file == mock_upload_file
|
||||
|
||||
# Test file response building
|
||||
response = file_preview_api._build_file_response(mock_generator, mock_upload_file, False)
|
||||
assert response is not None
|
||||
|
||||
# Verify storage was called correctly
|
||||
mock_storage.load.assert_not_called() # Since we're testing components separately
|
||||
|
||||
@patch("controllers.service_api.app.file_preview.storage")
|
||||
def test_storage_error_handling(
|
||||
self, mock_storage, file_preview_api, mock_app, mock_upload_file, mock_message_file, mock_message
|
||||
):
|
||||
"""Test storage error handling in the core logic"""
|
||||
file_id = str(uuid.uuid4())
|
||||
app_id = mock_app.id
|
||||
|
||||
# Set up mocks
|
||||
mock_upload_file.tenant_id = mock_app.tenant_id
|
||||
mock_message.app_id = app_id
|
||||
mock_message_file.upload_file_id = file_id
|
||||
mock_message_file.message_id = mock_message.id
|
||||
|
||||
# Mock storage error
|
||||
mock_storage.load.side_effect = Exception("Storage error")
|
||||
|
||||
with patch("controllers.service_api.app.file_preview.db") as mock_db:
|
||||
# Mock database queries for validation
|
||||
mock_db.session.query.return_value.where.return_value.first.side_effect = [
|
||||
mock_message_file, # MessageFile query
|
||||
mock_message, # Message query
|
||||
mock_upload_file, # UploadFile query
|
||||
mock_app, # App query for tenant validation
|
||||
]
|
||||
|
||||
# First validate file ownership works
|
||||
result_message_file, result_upload_file = file_preview_api._validate_file_ownership(file_id, app_id)
|
||||
assert result_message_file == mock_message_file
|
||||
assert result_upload_file == mock_upload_file
|
||||
|
||||
# Test storage error handling
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
mock_storage.load(mock_upload_file.key, stream=True)
|
||||
|
||||
assert "Storage error" in str(exc_info.value)
|
||||
|
||||
@patch("controllers.service_api.app.file_preview.logger")
|
||||
def test_validate_file_ownership_unexpected_error_logging(self, mock_logger, file_preview_api):
|
||||
"""Test that unexpected errors are logged properly"""
|
||||
file_id = str(uuid.uuid4())
|
||||
app_id = str(uuid.uuid4())
|
||||
|
||||
with patch("controllers.service_api.app.file_preview.db") as mock_db:
|
||||
# Mock database query to raise unexpected exception
|
||||
mock_db.session.query.side_effect = Exception("Unexpected database error")
|
||||
|
||||
# Execute and assert exception
|
||||
with pytest.raises(FileAccessDeniedError) as exc_info:
|
||||
file_preview_api._validate_file_ownership(file_id, app_id)
|
||||
|
||||
# Verify error message
|
||||
assert "File access validation failed" in str(exc_info.value)
|
||||
|
||||
# Verify logging was called
|
||||
mock_logger.exception.assert_called_once_with(
|
||||
"Unexpected error during file ownership validation",
|
||||
extra={"file_id": file_id, "app_id": app_id, "error": "Unexpected database error"},
|
||||
)
|
@@ -277,6 +277,85 @@ The text generation application offers non-session support and is ideal for tran
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/files/:file_id/preview'
|
||||
method='GET'
|
||||
title='File Preview'
|
||||
name='#file-preview'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
Preview or download uploaded files. This endpoint allows you to access files that have been previously uploaded via the File Upload API.
|
||||
|
||||
<i>Files can only be accessed if they belong to messages within the requesting application.</i>
|
||||
|
||||
### Path Parameters
|
||||
- `file_id` (string) Required
|
||||
The unique identifier of the file to preview, obtained from the File Upload API response.
|
||||
|
||||
### Query Parameters
|
||||
- `as_attachment` (boolean) Optional
|
||||
Whether to force download the file as an attachment. Default is `false` (preview in browser).
|
||||
|
||||
### Response
|
||||
Returns the file content with appropriate headers for browser display or download.
|
||||
- `Content-Type` Set based on file mime type
|
||||
- `Content-Length` File size in bytes (if available)
|
||||
- `Content-Disposition` Set to "attachment" if `as_attachment=true`
|
||||
- `Cache-Control` Caching headers for performance
|
||||
- `Accept-Ranges` Set to "bytes" for audio/video files
|
||||
|
||||
### Errors
|
||||
- 400, `invalid_param`, abnormal parameter input
|
||||
- 403, `file_access_denied`, file access denied or file does not belong to current application
|
||||
- 404, `file_not_found`, file not found or has been deleted
|
||||
- 500, internal server error
|
||||
|
||||
</Col>
|
||||
<Col sticky>
|
||||
### Request Example
|
||||
<CodeGroup title="Request" tag="GET" label="/files/:file_id/preview" targetCode={`curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview' \\\n--header 'Authorization: Bearer {api_key}'`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview' \
|
||||
--header 'Authorization: Bearer {api_key}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
### Download as Attachment
|
||||
<CodeGroup title="Download Request" tag="GET" label="/files/:file_id/preview?as_attachment=true" targetCode={`curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview?as_attachment=true' \\\n--header 'Authorization: Bearer {api_key}' \\\n--output downloaded_file.png`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview?as_attachment=true' \
|
||||
--header 'Authorization: Bearer {api_key}' \
|
||||
--output downloaded_file.png
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
### Response Headers Example
|
||||
<CodeGroup title="Response Headers">
|
||||
```http {{ title: 'Headers - Image Preview' }}
|
||||
Content-Type: image/png
|
||||
Content-Length: 1024
|
||||
Cache-Control: public, max-age=3600
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Download Response Headers
|
||||
<CodeGroup title="Download Response Headers">
|
||||
```http {{ title: 'Headers - File Download' }}
|
||||
Content-Type: image/png
|
||||
Content-Length: 1024
|
||||
Content-Disposition: attachment; filename*=UTF-8''example.png
|
||||
Cache-Control: public, max-age=3600
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/completion-messages/:task_id/stop'
|
||||
method='POST'
|
||||
|
@@ -276,6 +276,85 @@ import { Row, Col, Properties, Property, Heading, SubProperty, Paragraph } from
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/files/:file_id/preview'
|
||||
method='GET'
|
||||
title='ファイルプレビュー'
|
||||
name='#file-preview'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
アップロードされたファイルをプレビューまたはダウンロードします。このエンドポイントを使用すると、以前にファイルアップロード API でアップロードされたファイルにアクセスできます。
|
||||
|
||||
<i>ファイルは、リクエストしているアプリケーションのメッセージ範囲内にある場合のみアクセス可能です。</i>
|
||||
|
||||
### パスパラメータ
|
||||
- `file_id` (string) 必須
|
||||
プレビューするファイルの一意識別子。ファイルアップロード API レスポンスから取得します。
|
||||
|
||||
### クエリパラメータ
|
||||
- `as_attachment` (boolean) オプション
|
||||
ファイルを添付ファイルとして強制ダウンロードするかどうか。デフォルトは `false`(ブラウザでプレビュー)。
|
||||
|
||||
### レスポンス
|
||||
ブラウザ表示またはダウンロード用の適切なヘッダー付きでファイル内容を返します。
|
||||
- `Content-Type` ファイル MIME タイプに基づいて設定
|
||||
- `Content-Length` ファイルサイズ(バイト、利用可能な場合)
|
||||
- `Content-Disposition` `as_attachment=true` の場合は "attachment" に設定
|
||||
- `Cache-Control` パフォーマンス向上のためのキャッシュヘッダー
|
||||
- `Accept-Ranges` 音声/動画ファイルの場合は "bytes" に設定
|
||||
|
||||
### エラー
|
||||
- 400, `invalid_param`, パラメータ入力異常
|
||||
- 403, `file_access_denied`, ファイルアクセス拒否またはファイルが現在のアプリケーションに属していません
|
||||
- 404, `file_not_found`, ファイルが見つからないか削除されています
|
||||
- 500, サーバー内部エラー
|
||||
|
||||
</Col>
|
||||
<Col sticky>
|
||||
### リクエスト例
|
||||
<CodeGroup title="Request" tag="GET" label="/files/:file_id/preview" targetCode={`curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview' \\\n--header 'Authorization: Bearer {api_key}'`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview' \
|
||||
--header 'Authorization: Bearer {api_key}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
### 添付ファイルとしてダウンロード
|
||||
<CodeGroup title="Request" tag="GET" label="/files/:file_id/preview" targetCode={`curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview?as_attachment=true' \\\n--header 'Authorization: Bearer {api_key}' \\\n--output downloaded_file.png`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview?as_attachment=true' \
|
||||
--header 'Authorization: Bearer {api_key}' \
|
||||
--output downloaded_file.png
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
### レスポンスヘッダー例
|
||||
<CodeGroup title="Response Headers">
|
||||
```http {{ title: 'ヘッダー - 画像プレビュー' }}
|
||||
Content-Type: image/png
|
||||
Content-Length: 1024
|
||||
Cache-Control: public, max-age=3600
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### ファイルダウンロードレスポンスヘッダー
|
||||
<CodeGroup title="Response Headers">
|
||||
```http {{ title: 'ヘッダー - ファイルダウンロード' }}
|
||||
Content-Type: image/png
|
||||
Content-Length: 1024
|
||||
Content-Disposition: attachment; filename*=UTF-8''example.png
|
||||
Cache-Control: public, max-age=3600
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/completion-messages/:task_id/stop'
|
||||
method='POST'
|
||||
|
@@ -252,6 +252,86 @@ import { Row, Col, Properties, Property, Heading, SubProperty } from '../md.tsx'
|
||||
</Col>
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/files/:file_id/preview'
|
||||
method='GET'
|
||||
title='文件预览'
|
||||
name='#file-preview'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
预览或下载已上传的文件。此端点允许您访问先前通过文件上传 API 上传的文件。
|
||||
|
||||
<i>文件只能在属于请求应用程序的消息范围内访问。</i>
|
||||
|
||||
### 路径参数
|
||||
- `file_id` (string) 必需
|
||||
要预览的文件的唯一标识符,从文件上传 API 响应中获得。
|
||||
|
||||
### 查询参数
|
||||
- `as_attachment` (boolean) 可选
|
||||
是否强制将文件作为附件下载。默认为 `false`(在浏览器中预览)。
|
||||
|
||||
### 响应
|
||||
返回带有适当浏览器显示或下载标头的文件内容。
|
||||
- `Content-Type` 根据文件 MIME 类型设置
|
||||
- `Content-Length` 文件大小(以字节为单位,如果可用)
|
||||
- `Content-Disposition` 如果 `as_attachment=true` 则设置为 "attachment"
|
||||
- `Cache-Control` 用于性能的缓存标头
|
||||
- `Accept-Ranges` 对于音频/视频文件设置为 "bytes"
|
||||
|
||||
### 错误
|
||||
- 400, `invalid_param`, 参数输入异常
|
||||
- 403, `file_access_denied`, 文件访问被拒绝或文件不属于当前应用程序
|
||||
- 404, `file_not_found`, 文件未找到或已被删除
|
||||
- 500, 服务内部错误
|
||||
|
||||
</Col>
|
||||
<Col sticky>
|
||||
### 请求示例
|
||||
<CodeGroup title="Request" tag="GET" label="/files/:file_id/preview" targetCode={`curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview' \\\n--header 'Authorization: Bearer {api_key}'`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview' \
|
||||
--header 'Authorization: Bearer {api_key}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
### 作为附件下载
|
||||
<CodeGroup title="下载请求" tag="GET" label="/files/:file_id/preview?as_attachment=true" targetCode={`curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview?as_attachment=true' \\\n--header 'Authorization: Bearer {api_key}' \\\n--output downloaded_file.png`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview?as_attachment=true' \
|
||||
--header 'Authorization: Bearer {api_key}' \
|
||||
--output downloaded_file.png
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
### 响应标头示例
|
||||
<CodeGroup title="Response Headers">
|
||||
```http {{ title: 'Headers - 图片预览' }}
|
||||
Content-Type: image/png
|
||||
Content-Length: 1024
|
||||
Cache-Control: public, max-age=3600
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### 文件下载响应标头
|
||||
<CodeGroup title="Download Response Headers">
|
||||
```http {{ title: 'Headers - 文件下载' }}
|
||||
Content-Type: image/png
|
||||
Content-Length: 1024
|
||||
Content-Disposition: attachment; filename*=UTF-8''example.png
|
||||
Cache-Control: public, max-age=3600
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/completion-messages/:task_id/stop'
|
||||
method='POST'
|
||||
|
@@ -392,6 +392,85 @@ Chat applications support session persistence, allowing previous chat history to
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/files/:file_id/preview'
|
||||
method='GET'
|
||||
title='File Preview'
|
||||
name='#file-preview'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
Preview or download uploaded files. This endpoint allows you to access files that have been previously uploaded via the File Upload API.
|
||||
|
||||
<i>Files can only be accessed if they belong to messages within the requesting application.</i>
|
||||
|
||||
### Path Parameters
|
||||
- `file_id` (string) Required
|
||||
The unique identifier of the file to preview, obtained from the File Upload API response.
|
||||
|
||||
### Query Parameters
|
||||
- `as_attachment` (boolean) Optional
|
||||
Whether to force download the file as an attachment. Default is `false` (preview in browser).
|
||||
|
||||
### Response
|
||||
Returns the file content with appropriate headers for browser display or download.
|
||||
- `Content-Type` Set based on file mime type
|
||||
- `Content-Length` File size in bytes (if available)
|
||||
- `Content-Disposition` Set to "attachment" if `as_attachment=true`
|
||||
- `Cache-Control` Caching headers for performance
|
||||
- `Accept-Ranges` Set to "bytes" for audio/video files
|
||||
|
||||
### Errors
|
||||
- 400, `invalid_param`, abnormal parameter input
|
||||
- 403, `file_access_denied`, file access denied or file does not belong to current application
|
||||
- 404, `file_not_found`, file not found or has been deleted
|
||||
- 500, internal server error
|
||||
|
||||
</Col>
|
||||
<Col sticky>
|
||||
### Request Example
|
||||
<CodeGroup title="Request" tag="GET" label="/files/:file_id/preview" targetCode={`curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview' \\\n--header 'Authorization: Bearer {api_key}'`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview' \
|
||||
--header 'Authorization: Bearer {api_key}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
### Download as Attachment
|
||||
<CodeGroup title="Download Request" tag="GET" label="/files/:file_id/preview?as_attachment=true" targetCode={`curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview?as_attachment=true' \\\n--header 'Authorization: Bearer {api_key}' \\\n--output downloaded_file.png`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview?as_attachment=true' \
|
||||
--header 'Authorization: Bearer {api_key}' \
|
||||
--output downloaded_file.png
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
### Response Headers Example
|
||||
<CodeGroup title="Response Headers">
|
||||
```http {{ title: 'Headers - Image Preview' }}
|
||||
Content-Type: image/png
|
||||
Content-Length: 1024
|
||||
Cache-Control: public, max-age=3600
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Download Response Headers
|
||||
<CodeGroup title="Download Response Headers">
|
||||
```http {{ title: 'Headers - File Download' }}
|
||||
Content-Type: image/png
|
||||
Content-Length: 1024
|
||||
Content-Disposition: attachment; filename*=UTF-8''example.png
|
||||
Cache-Control: public, max-age=3600
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/chat-messages/:task_id/stop'
|
||||
method='POST'
|
||||
@@ -653,7 +732,7 @@ Chat applications support session persistence, allowing previous chat history to
|
||||
- `message_files` (array[object]) Message files
|
||||
- `id` (string) ID
|
||||
- `type` (string) File type, image for images
|
||||
- `url` (string) Preview image URL
|
||||
- `url` (string) File preview URL, use the File Preview API (`/files/{file_id}/preview`) to access the file
|
||||
- `belongs_to` (string) belongs to,user orassistant
|
||||
- `answer` (string) Response message content
|
||||
- `created_at` (timestamp) Creation timestamp, e.g., 1705395332
|
||||
|
@@ -654,7 +654,7 @@ import { Row, Col, Properties, Property, Heading, SubProperty, Paragraph } from
|
||||
- `message_files` (array[object]) メッセージファイル
|
||||
- `id` (string) ID
|
||||
- `type` (string) ファイルタイプ、画像の場合はimage
|
||||
- `url` (string) プレビュー画像URL
|
||||
- `url` (string) ファイルプレビューURL、ファイルアクセスにはファイルプレビューAPI(`/files/{file_id}/preview`)を使用してください
|
||||
- `belongs_to` (string) 所属、userまたはassistant
|
||||
- `answer` (string) 応答メッセージ内容
|
||||
- `created_at` (timestamp) 作成タイムスタンプ、例:1705395332
|
||||
@@ -1422,6 +1422,86 @@ import { Row, Col, Properties, Property, Heading, SubProperty, Paragraph } from
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/files/:file_id/preview'
|
||||
method='GET'
|
||||
title='ファイルプレビュー'
|
||||
name='#file-preview'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
アップロードされたファイルをプレビューまたはダウンロードします。このエンドポイントを使用すると、以前にファイルアップロード API でアップロードされたファイルにアクセスできます。
|
||||
|
||||
<i>ファイルは、リクエストしているアプリケーションのメッセージ範囲内にある場合のみアクセス可能です。</i>
|
||||
|
||||
### パスパラメータ
|
||||
- `file_id` (string) 必須
|
||||
プレビューするファイルの一意識別子。ファイルアップロード API レスポンスから取得します。
|
||||
|
||||
### クエリパラメータ
|
||||
- `as_attachment` (boolean) オプション
|
||||
ファイルを添付ファイルとして強制ダウンロードするかどうか。デフォルトは `false`(ブラウザでプレビュー)。
|
||||
|
||||
### レスポンス
|
||||
ブラウザ表示またはダウンロード用の適切なヘッダー付きでファイル内容を返します。
|
||||
- `Content-Type` ファイル MIME タイプに基づいて設定
|
||||
- `Content-Length` ファイルサイズ(バイト、利用可能な場合)
|
||||
- `Content-Disposition` `as_attachment=true` の場合は "attachment" に設定
|
||||
- `Cache-Control` パフォーマンス向上のためのキャッシュヘッダー
|
||||
- `Accept-Ranges` 音声/動画ファイルの場合は "bytes" に設定
|
||||
|
||||
### エラー
|
||||
- 400, `invalid_param`, パラメータ入力異常
|
||||
- 403, `file_access_denied`, ファイルアクセス拒否またはファイルが現在のアプリケーションに属していません
|
||||
- 404, `file_not_found`, ファイルが見つからないか削除されています
|
||||
- 500, サーバー内部エラー
|
||||
|
||||
</Col>
|
||||
<Col sticky>
|
||||
### リクエスト例
|
||||
<CodeGroup title="Request" tag="GET" label="/files/:file_id/preview" targetCode={`curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview' \\\n--header 'Authorization: Bearer {api_key}'`}>
|
||||
|
||||
```bash {{ title: 'cURL - ブラウザプレビュー' }}
|
||||
curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview' \
|
||||
--header 'Authorization: Bearer {api_key}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
### 添付ファイルとしてダウンロード
|
||||
<CodeGroup title="Download Request" tag="GET" label="/files/:file_id/preview?as_attachment=true" targetCode={`curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview?as_attachment=true' \\\n--header 'Authorization: Bearer {api_key}' \\\n--output downloaded_file.png`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview?as_attachment=true' \
|
||||
--header 'Authorization: Bearer {api_key}' \
|
||||
--output downloaded_file.png
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
### レスポンスヘッダー例
|
||||
<CodeGroup title="Response Headers">
|
||||
```http {{ title: 'ヘッダー - 画像プレビュー' }}
|
||||
Content-Type: image/png
|
||||
Content-Length: 1024
|
||||
Cache-Control: public, max-age=3600
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### ダウンロードレスポンスヘッダー
|
||||
<CodeGroup title="Download Response Headers">
|
||||
```http {{ title: 'ヘッダー - ファイルダウンロード' }}
|
||||
Content-Type: image/png
|
||||
Content-Length: 1024
|
||||
Content-Disposition: attachment; filename*=UTF-8''example.png
|
||||
Cache-Control: public, max-age=3600
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/meta'
|
||||
method='GET'
|
||||
|
@@ -399,6 +399,86 @@ import { Row, Col, Properties, Property, Heading, SubProperty } from '../md.tsx'
|
||||
</Col>
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/files/:file_id/preview'
|
||||
method='GET'
|
||||
title='文件预览'
|
||||
name='#file-preview'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
预览或下载已上传的文件。此端点允许您访问先前通过文件上传 API 上传的文件。
|
||||
|
||||
<i>文件只能在属于请求应用程序的消息范围内访问。</i>
|
||||
|
||||
### 路径参数
|
||||
- `file_id` (string) 必需
|
||||
要预览的文件的唯一标识符,从文件上传 API 响应中获得。
|
||||
|
||||
### 查询参数
|
||||
- `as_attachment` (boolean) 可选
|
||||
是否强制将文件作为附件下载。默认为 `false`(在浏览器中预览)。
|
||||
|
||||
### 响应
|
||||
返回带有适当浏览器显示或下载标头的文件内容。
|
||||
- `Content-Type` 根据文件 MIME 类型设置
|
||||
- `Content-Length` 文件大小(以字节为单位,如果可用)
|
||||
- `Content-Disposition` 如果 `as_attachment=true` 则设置为 "attachment"
|
||||
- `Cache-Control` 用于性能的缓存标头
|
||||
- `Accept-Ranges` 对于音频/视频文件设置为 "bytes"
|
||||
|
||||
### 错误
|
||||
- 400, `invalid_param`, 参数输入异常
|
||||
- 403, `file_access_denied`, 文件访问被拒绝或文件不属于当前应用程序
|
||||
- 404, `file_not_found`, 文件未找到或已被删除
|
||||
- 500, 服务内部错误
|
||||
|
||||
</Col>
|
||||
<Col sticky>
|
||||
### 请求示例
|
||||
<CodeGroup title="Request" tag="GET" label="/files/:file_id/preview" targetCode={`curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview' \\\n--header 'Authorization: Bearer {api_key}'`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview' \
|
||||
--header 'Authorization: Bearer {api_key}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
### 作为附件下载
|
||||
<CodeGroup title="Request" tag="GET" label="/files/:file_id/preview?as_attachment=true" targetCode={`curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview?as_attachment=true' \\\n--header 'Authorization: Bearer {api_key}' \\\n--output downloaded_file.png`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview?as_attachment=true' \
|
||||
--header 'Authorization: Bearer {api_key}' \
|
||||
--output downloaded_file.png
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
### 响应标头示例
|
||||
<CodeGroup title="Response Headers">
|
||||
```http {{ title: 'Headers - 图片预览' }}
|
||||
Content-Type: image/png
|
||||
Content-Length: 1024
|
||||
Cache-Control: public, max-age=3600
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### 文件下载响应标头
|
||||
<CodeGroup title="Download Response Headers">
|
||||
```http {{ title: 'Headers - 文件下载' }}
|
||||
Content-Type: image/png
|
||||
Content-Length: 1024
|
||||
Content-Disposition: attachment; filename*=UTF-8''example.png
|
||||
Cache-Control: public, max-age=3600
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/chat-messages/:task_id/stop'
|
||||
method='POST'
|
||||
@@ -661,7 +741,7 @@ import { Row, Col, Properties, Property, Heading, SubProperty } from '../md.tsx'
|
||||
- `message_files` (array[object]) 消息文件
|
||||
- `id` (string) ID
|
||||
- `type` (string) 文件类型,image 图片
|
||||
- `url` (string) 预览图片地址
|
||||
- `url` (string) 文件预览地址,使用文件预览 API (`/files/{file_id}/preview`) 访问文件
|
||||
- `belongs_to` (string) 文件归属方,user 或 assistant
|
||||
- `answer` (string) 回答消息内容
|
||||
- `created_at` (timestamp) 创建时间
|
||||
|
@@ -356,6 +356,85 @@ Chat applications support session persistence, allowing previous chat history to
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/files/:file_id/preview'
|
||||
method='GET'
|
||||
title='File Preview'
|
||||
name='#file-preview'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
Preview or download uploaded files. This endpoint allows you to access files that have been previously uploaded via the File Upload API.
|
||||
|
||||
<i>Files can only be accessed if they belong to messages within the requesting application.</i>
|
||||
|
||||
### Path Parameters
|
||||
- `file_id` (string) Required
|
||||
The unique identifier of the file to preview, obtained from the File Upload API response.
|
||||
|
||||
### Query Parameters
|
||||
- `as_attachment` (boolean) Optional
|
||||
Whether to force download the file as an attachment. Default is `false` (preview in browser).
|
||||
|
||||
### Response
|
||||
Returns the file content with appropriate headers for browser display or download.
|
||||
- `Content-Type` Set based on file mime type
|
||||
- `Content-Length` File size in bytes (if available)
|
||||
- `Content-Disposition` Set to "attachment" if `as_attachment=true`
|
||||
- `Cache-Control` Caching headers for performance
|
||||
- `Accept-Ranges` Set to "bytes" for audio/video files
|
||||
|
||||
### Errors
|
||||
- 400, `invalid_param`, abnormal parameter input
|
||||
- 403, `file_access_denied`, file access denied or file does not belong to current application
|
||||
- 404, `file_not_found`, file not found or has been deleted
|
||||
- 500, internal server error
|
||||
|
||||
</Col>
|
||||
<Col sticky>
|
||||
### Request Example
|
||||
<CodeGroup title="Request" tag="GET" label="/files/:file_id/preview" targetCode={`curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview' \\\n--header 'Authorization: Bearer {api_key}'`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview' \
|
||||
--header 'Authorization: Bearer {api_key}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
### Download as Attachment
|
||||
<CodeGroup title="Download Request" tag="GET" label="/files/:file_id/preview?as_attachment=true" targetCode={`curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview?as_attachment=true' \\\n--header 'Authorization: Bearer {api_key}' \\\n--output downloaded_file.png`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview?as_attachment=true' \
|
||||
--header 'Authorization: Bearer {api_key}' \
|
||||
--output downloaded_file.png
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
### Response Headers Example
|
||||
<CodeGroup title="Response Headers">
|
||||
```http {{ title: 'Headers - Image Preview' }}
|
||||
Content-Type: image/png
|
||||
Content-Length: 1024
|
||||
Cache-Control: public, max-age=3600
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Download Response Headers
|
||||
<CodeGroup title="Download Response Headers">
|
||||
```http {{ title: 'Headers - File Download' }}
|
||||
Content-Type: image/png
|
||||
Content-Length: 1024
|
||||
Content-Disposition: attachment; filename*=UTF-8''example.png
|
||||
Cache-Control: public, max-age=3600
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/chat-messages/:task_id/stop'
|
||||
method='POST'
|
||||
@@ -617,7 +696,7 @@ Chat applications support session persistence, allowing previous chat history to
|
||||
- `message_files` (array[object]) Message files
|
||||
- `id` (string) ID
|
||||
- `type` (string) File type, image for images
|
||||
- `url` (string) Preview image URL
|
||||
- `url` (string) File preview URL, use the File Preview API (`/files/{file_id}/preview`) to access the file
|
||||
- `belongs_to` (string) belongs to,user or assistant
|
||||
- `agent_thoughts` (array[object]) Agent thought(Empty if it's a Basic Assistant)
|
||||
- `id` (string) Agent thought ID, every iteration has a unique agent thought ID
|
||||
|
@@ -356,6 +356,85 @@ import { Row, Col, Properties, Property, Heading, SubProperty, Paragraph } from
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/files/:file_id/preview'
|
||||
method='GET'
|
||||
title='ファイルプレビュー'
|
||||
name='#file-preview'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
アップロードされたファイルをプレビューまたはダウンロードします。このエンドポイントを使用すると、以前にファイルアップロード API でアップロードされたファイルにアクセスできます。
|
||||
|
||||
<i>ファイルは、リクエストしているアプリケーションのメッセージ範囲内にある場合のみアクセス可能です。</i>
|
||||
|
||||
### パスパラメータ
|
||||
- `file_id` (string) 必須
|
||||
プレビューするファイルの一意識別子。ファイルアップロード API レスポンスから取得します。
|
||||
|
||||
### クエリパラメータ
|
||||
- `as_attachment` (boolean) オプション
|
||||
ファイルを添付ファイルとして強制ダウンロードするかどうか。デフォルトは `false`(ブラウザでプレビュー)。
|
||||
|
||||
### レスポンス
|
||||
ブラウザ表示またはダウンロード用の適切なヘッダー付きでファイル内容を返します。
|
||||
- `Content-Type` ファイル MIME タイプに基づいて設定
|
||||
- `Content-Length` ファイルサイズ(バイト、利用可能な場合)
|
||||
- `Content-Disposition` `as_attachment=true` の場合は "attachment" に設定
|
||||
- `Cache-Control` パフォーマンス向上のためのキャッシュヘッダー
|
||||
- `Accept-Ranges` 音声/動画ファイルの場合は "bytes" に設定
|
||||
|
||||
### エラー
|
||||
- 400, `invalid_param`, パラメータ入力異常
|
||||
- 403, `file_access_denied`, ファイルアクセス拒否またはファイルが現在のアプリケーションに属していません
|
||||
- 404, `file_not_found`, ファイルが見つからないか削除されています
|
||||
- 500, サーバー内部エラー
|
||||
|
||||
</Col>
|
||||
<Col sticky>
|
||||
### リクエスト例
|
||||
<CodeGroup title="Request" tag="GET" label="/files/:file_id/preview" targetCode={`curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview' \\\n--header 'Authorization: Bearer {api_key}'`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview' \
|
||||
--header 'Authorization: Bearer {api_key}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
### 添付ファイルとしてダウンロード
|
||||
<CodeGroup title="Download Request" tag="GET" label="/files/:file_id/preview?as_attachment=true" targetCode={`curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview?as_attachment=true' \\\n--header 'Authorization: Bearer {api_key}' \\\n--output downloaded_file.png`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview?as_attachment=true' \
|
||||
--header 'Authorization: Bearer {api_key}' \
|
||||
--output downloaded_file.png
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
### レスポンスヘッダー例
|
||||
<CodeGroup title="Response Headers">
|
||||
```http {{ title: 'Headers - 画像プレビュー' }}
|
||||
Content-Type: image/png
|
||||
Content-Length: 1024
|
||||
Cache-Control: public, max-age=3600
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### ダウンロードレスポンスヘッダー
|
||||
<CodeGroup title="Download Response Headers">
|
||||
```http {{ title: 'Headers - ファイルダウンロード' }}
|
||||
Content-Type: image/png
|
||||
Content-Length: 1024
|
||||
Content-Disposition: attachment; filename*=UTF-8''example.png
|
||||
Cache-Control: public, max-age=3600
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/chat-messages/:task_id/stop'
|
||||
method='POST'
|
||||
@@ -618,7 +697,7 @@ import { Row, Col, Properties, Property, Heading, SubProperty, Paragraph } from
|
||||
- `message_files` (array[object]) メッセージファイル
|
||||
- `id` (string) ID
|
||||
- `type` (string) ファイルタイプ、画像の場合はimage
|
||||
- `url` (string) プレビュー画像URL
|
||||
- `url` (string) ファイルプレビューURL、ファイルアクセスにはファイルプレビューAPI(`/files/{file_id}/preview`)を使用してください
|
||||
- `belongs_to` (string) 所属、ユーザーまたはアシスタント
|
||||
- `agent_thoughts` (array[object]) エージェントの思考(基本アシスタントの場合は空)
|
||||
- `id` (string) エージェント思考ID、各反復には一意のエージェント思考IDがあります
|
||||
|
@@ -371,6 +371,86 @@ import { Row, Col, Properties, Property, Heading, SubProperty } from '../md.tsx'
|
||||
</Col>
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/files/:file_id/preview'
|
||||
method='GET'
|
||||
title='文件预览'
|
||||
name='#file-preview'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
预览或下载已上传的文件。此端点允许您访问先前通过文件上传 API 上传的文件。
|
||||
|
||||
<i>文件只能在属于请求应用程序的消息范围内访问。</i>
|
||||
|
||||
### 路径参数
|
||||
- `file_id` (string) 必需
|
||||
要预览的文件的唯一标识符,从文件上传 API 响应中获得。
|
||||
|
||||
### 查询参数
|
||||
- `as_attachment` (boolean) 可选
|
||||
是否强制将文件作为附件下载。默认为 `false`(在浏览器中预览)。
|
||||
|
||||
### 响应
|
||||
返回带有适当浏览器显示或下载标头的文件内容。
|
||||
- `Content-Type` 根据文件 MIME 类型设置
|
||||
- `Content-Length` 文件大小(以字节为单位,如果可用)
|
||||
- `Content-Disposition` 如果 `as_attachment=true` 则设置为 "attachment"
|
||||
- `Cache-Control` 用于性能的缓存标头
|
||||
- `Accept-Ranges` 对于音频/视频文件设置为 "bytes"
|
||||
|
||||
### 错误
|
||||
- 400, `invalid_param`, 参数输入异常
|
||||
- 403, `file_access_denied`, 文件访问被拒绝或文件不属于当前应用程序
|
||||
- 404, `file_not_found`, 文件未找到或已被删除
|
||||
- 500, 服务内部错误
|
||||
|
||||
</Col>
|
||||
<Col sticky>
|
||||
### 请求示例
|
||||
<CodeGroup title="Request" tag="GET" label="/files/:file_id/preview" targetCode={`curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview' \\\n--header 'Authorization: Bearer {api_key}'`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview' \
|
||||
--header 'Authorization: Bearer {api_key}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
### 作为附件下载
|
||||
<CodeGroup title="Request" tag="GET" label="/files/:file_id/preview?as_attachment=true" targetCode={`curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview?as_attachment=true' \\\\\\n--header 'Authorization: Bearer {api_key}' \\\\\\n--output downloaded_file.png`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview?as_attachment=true' \
|
||||
--header 'Authorization: Bearer {api_key}' \
|
||||
--output downloaded_file.png
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
### 响应标头示例
|
||||
<CodeGroup title="Response Headers">
|
||||
```http {{ title: 'Headers - 图片预览' }}
|
||||
Content-Type: image/png
|
||||
Content-Length: 1024
|
||||
Cache-Control: public, max-age=3600
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### 文件下载响应标头
|
||||
<CodeGroup title="Download Response Headers">
|
||||
```http {{ title: 'Headers - 文件下载' }}
|
||||
Content-Type: image/png
|
||||
Content-Length: 1024
|
||||
Content-Disposition: attachment; filename*=UTF-8''example.png
|
||||
Cache-Control: public, max-age=3600
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/chat-messages/:task_id/stop'
|
||||
method='POST'
|
||||
@@ -631,7 +711,7 @@ import { Row, Col, Properties, Property, Heading, SubProperty } from '../md.tsx'
|
||||
- `message_files` (array[object]) 消息文件
|
||||
- `id` (string) ID
|
||||
- `type` (string) 文件类型,image 图片
|
||||
- `url` (string) 预览图片地址
|
||||
- `url` (string) 文件预览地址,使用文件预览 API (`/files/{file_id}/preview`) 访问文件
|
||||
- `belongs_to` (string) 文件归属方,user 或 assistant
|
||||
- `agent_thoughts` (array[object]) Agent思考内容(仅Agent模式下不为空)
|
||||
- `id` (string) agent_thought ID,每一轮Agent迭代都会有一个唯一的id
|
||||
|
@@ -747,6 +747,86 @@ Workflow applications offers non-session support and is ideal for translation, a
|
||||
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/files/:file_id/preview'
|
||||
method='GET'
|
||||
title='File Preview'
|
||||
name='#file-preview'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
Preview or download uploaded files. This endpoint allows you to access files that have been previously uploaded via the File Upload API.
|
||||
|
||||
<i>Files can only be accessed if they belong to messages within the requesting application.</i>
|
||||
|
||||
### Path Parameters
|
||||
- `file_id` (string) Required
|
||||
The unique identifier of the file to preview, obtained from the File Upload API response.
|
||||
|
||||
### Query Parameters
|
||||
- `as_attachment` (boolean) Optional
|
||||
Whether to force download the file as an attachment. Default is `false` (preview in browser).
|
||||
|
||||
### Response
|
||||
Returns the file content with appropriate headers for browser display or download.
|
||||
- `Content-Type` Set based on file mime type
|
||||
- `Content-Length` File size in bytes (if available)
|
||||
- `Content-Disposition` Set to "attachment" if `as_attachment=true`
|
||||
- `Cache-Control` Caching headers for performance
|
||||
- `Accept-Ranges` Set to "bytes" for audio/video files
|
||||
|
||||
### Errors
|
||||
- 400, `invalid_param`, abnormal parameter input
|
||||
- 403, `file_access_denied`, file access denied or file does not belong to current application
|
||||
- 404, `file_not_found`, file not found or has been deleted
|
||||
- 500, internal server error
|
||||
|
||||
</Col>
|
||||
<Col sticky>
|
||||
### Request Example
|
||||
<CodeGroup title="Request" tag="GET" label="/files/:file_id/preview" targetCode={`curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview' \\\n--header 'Authorization: Bearer {api_key}'`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview' \
|
||||
--header 'Authorization: Bearer {api_key}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
### Download as Attachment
|
||||
<CodeGroup title="Download Request" tag="GET" label="/files/:file_id/preview?as_attachment=true" targetCode={`curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview?as_attachment=true' \\\n--header 'Authorization: Bearer {api_key}' \\\n--output downloaded_file.png`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview?as_attachment=true' \
|
||||
--header 'Authorization: Bearer {api_key}' \
|
||||
--output downloaded_file.png
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
### Response Headers Example
|
||||
<CodeGroup title="Response Headers">
|
||||
```http {{ title: 'Headers - Image Preview' }}
|
||||
Content-Type: image/png
|
||||
Content-Length: 1024
|
||||
Cache-Control: public, max-age=3600
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Download Response Headers
|
||||
<CodeGroup title="Download Response Headers">
|
||||
```http {{ title: 'Headers - File Download' }}
|
||||
Content-Type: image/png
|
||||
Content-Length: 1024
|
||||
Content-Disposition: attachment; filename*=UTF-8''example.png
|
||||
Cache-Control: public, max-age=3600
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/workflows/logs'
|
||||
method='GET'
|
||||
|
@@ -742,6 +742,86 @@ import { Row, Col, Properties, Property, Heading, SubProperty, Paragraph } from
|
||||
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/files/:file_id/preview'
|
||||
method='GET'
|
||||
title='ファイルプレビュー'
|
||||
name='#file-preview'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
アップロードされたファイルをプレビューまたはダウンロードします。このエンドポイントを使用すると、以前にファイルアップロード API でアップロードされたファイルにアクセスできます。
|
||||
|
||||
<i>ファイルは、リクエストしているアプリケーションのメッセージ範囲内にある場合のみアクセス可能です。</i>
|
||||
|
||||
### パスパラメータ
|
||||
- `file_id` (string) 必須
|
||||
プレビューするファイルの一意識別子。ファイルアップロード API レスポンスから取得します。
|
||||
|
||||
### クエリパラメータ
|
||||
- `as_attachment` (boolean) オプション
|
||||
ファイルを添付ファイルとして強制ダウンロードするかどうか。デフォルトは `false`(ブラウザでプレビュー)。
|
||||
|
||||
### レスポンス
|
||||
ブラウザ表示またはダウンロード用の適切なヘッダー付きでファイル内容を返します。
|
||||
- `Content-Type` ファイル MIME タイプに基づいて設定
|
||||
- `Content-Length` ファイルサイズ(バイト、利用可能な場合)
|
||||
- `Content-Disposition` `as_attachment=true` の場合は "attachment" に設定
|
||||
- `Cache-Control` パフォーマンス向上のためのキャッシュヘッダー
|
||||
- `Accept-Ranges` 音声/動画ファイルの場合は "bytes" に設定
|
||||
|
||||
### エラー
|
||||
- 400, `invalid_param`, パラメータ入力異常
|
||||
- 403, `file_access_denied`, ファイルアクセス拒否またはファイルが現在のアプリケーションに属していません
|
||||
- 404, `file_not_found`, ファイルが見つからないか削除されています
|
||||
- 500, サーバー内部エラー
|
||||
|
||||
</Col>
|
||||
<Col sticky>
|
||||
### リクエスト例
|
||||
<CodeGroup title="Request" tag="GET" label="/files/:file_id/preview" targetCode={`curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview' \\\n--header 'Authorization: Bearer {api_key}'`}>
|
||||
|
||||
```bash {{ title: 'cURL - ブラウザプレビュー' }}
|
||||
curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview' \
|
||||
--header 'Authorization: Bearer {api_key}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
### 添付ファイルとしてダウンロード
|
||||
<CodeGroup title="Download Request" tag="GET" label="/files/:file_id/preview?as_attachment=true" targetCode={`curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview?as_attachment=true' \\\n--header 'Authorization: Bearer {api_key}' \\\n--output downloaded_file.png`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview?as_attachment=true' \
|
||||
--header 'Authorization: Bearer {api_key}' \
|
||||
--output downloaded_file.png
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
### レスポンスヘッダー例
|
||||
<CodeGroup title="Response Headers">
|
||||
```http {{ title: 'ヘッダー - 画像プレビュー' }}
|
||||
Content-Type: image/png
|
||||
Content-Length: 1024
|
||||
Cache-Control: public, max-age=3600
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### ダウンロードレスポンスヘッダー
|
||||
<CodeGroup title="Download Response Headers">
|
||||
```http {{ title: 'ヘッダー - ファイルダウンロード' }}
|
||||
Content-Type: image/png
|
||||
Content-Length: 1024
|
||||
Content-Disposition: attachment; filename*=UTF-8''example.png
|
||||
Cache-Control: public, max-age=3600
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/workflows/logs'
|
||||
method='GET'
|
||||
|
@@ -730,6 +730,85 @@ Workflow 应用无会话支持,适合用于翻译/文章写作/总结 AI 等
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/files/:file_id/preview'
|
||||
method='GET'
|
||||
title='文件预览'
|
||||
name='#file-preview'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
预览或下载已上传的文件。此端点允许您访问先前通过文件上传 API 上传的文件。
|
||||
|
||||
<i>文件只能在属于请求应用程序的消息范围内访问。</i>
|
||||
|
||||
### 路径参数
|
||||
- `file_id` (string) 必需
|
||||
要预览的文件的唯一标识符,从文件上传 API 响应中获得。
|
||||
|
||||
### 查询参数
|
||||
- `as_attachment` (boolean) 可选
|
||||
是否强制将文件作为附件下载。默认为 `false`(在浏览器中预览)。
|
||||
|
||||
### 响应
|
||||
返回带有适当浏览器显示或下载标头的文件内容。
|
||||
- `Content-Type` 根据文件 MIME 类型设置
|
||||
- `Content-Length` 文件大小(以字节为单位,如果可用)
|
||||
- `Content-Disposition` 如果 `as_attachment=true` 则设置为 "attachment"
|
||||
- `Cache-Control` 用于性能的缓存标头
|
||||
- `Accept-Ranges` 对于音频/视频文件设置为 "bytes"
|
||||
|
||||
### 错误
|
||||
- 400, `invalid_param`, 参数输入异常
|
||||
- 403, `file_access_denied`, 文件访问被拒绝或文件不属于当前应用程序
|
||||
- 404, `file_not_found`, 文件未找到或已被删除
|
||||
- 500, 服务内部错误
|
||||
|
||||
</Col>
|
||||
<Col sticky>
|
||||
### 请求示例
|
||||
<CodeGroup title="Request" tag="GET" label="/files/:file_id/preview" targetCode={`curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview' \\\n--header 'Authorization: Bearer {api_key}'`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview' \
|
||||
--header 'Authorization: Bearer {api_key}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
### 作为附件下载
|
||||
<CodeGroup title="Request" tag="GET" label="/files/:file_id/preview?as_attachment=true" targetCode={`curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview?as_attachment=true' \\\\\\n--header 'Authorization: Bearer {api_key}' \\\\\\n--output downloaded_file.png`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl -X GET '${props.appDetail.api_base_url}/files/72fa9618-8f89-4a37-9b33-7e1178a24a67/preview?as_attachment=true' \
|
||||
--header 'Authorization: Bearer {api_key}' \
|
||||
--output downloaded_file.png
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
### 响应标头示例
|
||||
<CodeGroup title="Response Headers">
|
||||
```http {{ title: 'Headers - 图片预览' }}
|
||||
Content-Type: image/png
|
||||
Content-Length: 1024
|
||||
Cache-Control: public, max-age=3600
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### 文件下载响应标头
|
||||
<CodeGroup title="Download Response Headers">
|
||||
```http {{ title: 'Headers - 文件下载' }}
|
||||
Content-Type: image/png
|
||||
Content-Length: 1024
|
||||
Content-Disposition: attachment; filename*=UTF-8''example.png
|
||||
Cache-Control: public, max-age=3600
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/workflows/logs'
|
||||
method='GET'
|
||||
|
Reference in New Issue
Block a user