File uploads

Upload with presigned OSS URLs or use one-step URL, multipart stream, and Base64 endpoints.

HopsAPI provides two upload families:

  • Direct OSS upload for browsers, large files, and high concurrency. File bytes bypass the HopsAPI gateway.
  • One-step compatibility endpoints for remote URLs, multipart file streams, and Base64. A successful request immediately returns a public fileUrl suitable for media inputs.

Every endpoint requires a HopsAPI API key through Authorization: Bearer sk-... or x-api-key. The three one-step endpoints create public temporary objects that are expected to be removed by the OSS lifecycle rule after 24 hours by default.

expiresAt is calculated from the gateway's OSS_TEMP_OBJECT_TTL_SEC setting. Operations must configure a matching OSS lifecycle rule for public/tmp/; the API does not scan or delete objects itself.

Method comparison

MethodEndpointBest forDefault limit
Direct OSS/api/v1/asset/get-presigned-url + /api/v1/asset/registerLarge files, browsers, private objectsControlled by OSS policy
URL upload/api/file-url-uploadImporting a public remote file into the HopsAPI CDN100 MB
Stream upload/api/file-stream-uploadUploading a local file directly100 MB
Base64 upload/api/file-base64-uploadSmall files and JSON-only integrations10 MB decoded

uploadPath and fileName are optional. Unsafe characters are sanitized, and the real object name includes a UUID, so an upload never overwrites an older object with the same name.

One-step response

All three compatibility endpoints return the same success structure:

{
  "success": true,
  "code": 200,
  "msg": "文件上传成功",
  "data": {
    "fileId": "file_550e8400e29b41d4a716446655440000",
    "fileName": "reference.png",
    "originalName": "reference.png",
    "fileSize": 245760,
    "mimeType": "image/png",
    "uploadPath": "images",
    "fileUrl": "https://assets.example.com/public/tmp/42/images/...-reference.png",
    "downloadUrl": "https://assets.example.com/public/tmp/42/images/...-reference.png",
    "uploadTime": "2026-07-24T06:00:00.000Z",
    "expiresAt": "2026-07-25T06:00:00.000Z"
  }
}

fileId has a stable identifier format for this response, but the current implementation does not create a queryable asset database record. Public temporary objects use the same URL for fileUrl and downloadUrl.

URL upload

POST/api/file-url-upload

Downloads a public HTTP(S) file and stores it under the current account's temporary public prefix.

{
  "fileUrl": "https://example.com/reference.png",
  "uploadPath": "images",
  "fileName": "reference.png"
}
FieldTypeRequiredDescription
fileUrlstringYesPublicly reachable HTTP(S) file URL.
uploadPathstringNoLogical path such as images/references. At most eight sanitized segments are retained.
fileNamestringNoDisplay file name. When omitted, it is derived from the final URL.
curl https://hopsapi.com/api/file-url-upload \
  -H "Authorization: Bearer sk-YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "fileUrl": "https://example.com/reference.png",
    "uploadPath": "images",
    "fileName": "reference.png"
  }'

URL imports default to a 30-second timeout, five redirects, and 100 MB. Every resolution and redirect rejects localhost, private, loopback, link-local, reserved, credential-bearing, and otherwise non-public targets to reduce SSRF risk.

Stream upload

POST/api/file-stream-upload

Uploads a local file using multipart/form-data.

FieldTypeRequiredDescription
filefileYesLocal file, 100 MB by default.
uploadPathstringNoLogical path.
fileNamestringNoDisplay file name. The multipart file name is used when omitted.
curl https://hopsapi.com/api/file-stream-upload \
  -H "Authorization: Bearer sk-YOUR_KEY" \
  -F "file=@./reference.png" \
  -F "uploadPath=images" \
  -F "fileName=reference.png"

Stream bytes pass through the HopsAPI gateway before being uploaded to OSS. Prefer direct OSS upload for large files or high concurrency.

Base64 upload

POST/api/file-base64-upload

Uploads raw Base64 or a Data URL in a JSON request.

{
  "base64Data": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...",
  "uploadPath": "images",
  "fileName": "reference.png"
}
FieldTypeRequiredDescription
base64DatastringYesRaw Base64 or data:<mime>;base64,...; 10 MB decoded by default.
uploadPathstringNoLogical path.
fileNamestringNoDisplay name. When omitted, a random name is generated from the Data URL MIME type.
curl https://hopsapi.com/api/file-base64-upload \
  -H "Authorization: Bearer sk-YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "base64Data": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...",
    "uploadPath": "images",
    "fileName": "reference.png"
  }'

Base64 increases request size by about 33%. Use stream or direct OSS upload for files larger than 10 MB.

Direct presigned OSS upload

The existing three-step flow remains unchanged and is still recommended for large files:

  1. Call POST /api/v1/asset/get-presigned-url with file metadata and visibility.
  2. Send the file bytes directly to the returned signed_url with HTTP PUT.
  3. Call POST /api/v1/asset/register with object_key to verify the object and obtain file_url.

1. Request an upload URL

POST/api/v1/asset/get-presigned-url

Creates an account-scoped object key and temporary presigned OSS upload URL.

{
  "file_name": "report.pdf",
  "content_type": "application/pdf",
  "is_public": false
}
FieldTypeRequiredDescription
file_namestringYesOriginal name. Directory components are removed and unsafe characters replaced.
content_typestringYesMIME type used for the upload signature.
is_publicbooleanYestrue returns a public CDN URL; false returns a temporary signed download URL.

Response:

{
  "object_key": "private/tmp/42/550e8400-e29b-41d4-a716-446655440000-report.pdf",
  "signed_url": "https://assets.example.com/private/tmp/42/...?OSSAccessKeyId=..."
}

The upload URL expires after approximately ten minutes by default. Keep object_key for registration.

2. PUT the file

curl --request PUT "SIGNED_URL" \
  --header "Content-Type: application/pdf" \
  --upload-file ./report.pdf

Content-Type must exactly match the content_type used to request the signature. Do not add the HopsAPI Authorization header to the OSS request, and do not log or share signed URLs.

3. Register the object

POST/api/v1/asset/register

Verifies that the object belongs to the current account and exists, then returns its public or private access URL.

{
  "object_key": "private/tmp/42/550e8400-e29b-41d4-a716-446655440000-report.pdf",
  "name": "Quarterly report"
}

Response:

{
  "name": "Quarterly report",
  "type": "application/pdf",
  "file_url": "https://assets.example.com/private/tmp/42/...?OSSAccessKeyId=..."
}

Public objects return an unauthenticated CDN URL. Private objects return a signed GET URL valid for approximately one hour by default. Call registration again with the same object_key to refresh a private URL.

Errors

One-step compatibility endpoints use:

{
  "success": false,
  "code": 413,
  "msg": "文件超过大小限制",
  "data": null
}
HTTP statusMeaning
400Invalid body, Base64, URL, or missing required field
401Missing, invalid, or inactive API key
413Request body or file exceeds the endpoint limit
502Remote download or OSS upload failed

Validation, authentication, size, and upstream failures use the compatibility shape above. File endpoints do not use the LLM account limits or the retired shared per-key/per-IP allowance.

The existing presign and registration endpoints keep their OpenAI-compatible error object. OSS PUT failures are returned directly by OSS.

On this page

On this page