Object Storage - Browser-based uploads using POST
Find out how to let end users upload files directly from their browser to an OVHcloud Object Storage bucket using a server-signed HTML form
Objective
This guide explains how to implement browser-based direct uploads to OVHcloud Object Storage using the HTTP POST method, with server-side POST Policy generation and SigV4 authentication.
Requirements
- A Public Cloud project in your OVHcloud account
- An Object Storage user already created
- AWS CLI installed and configured
Instructions
Overview
Browser-based POST uploads allow web applications to let end users upload files directly to an OVHcloud Object Storage bucket, without routing file data through your application server. Your backend generates a policy and signature, the user selects a file, and the browser sends the upload directly to the bucket.
The upload flow consists of the following steps:
- Your backend generates a POST Policy (a JSON document defining upload constraints) and signs it with a SigV4 HMAC-SHA256 signature.
- Your HTML page contains a form embedding the policy, signature, and object metadata as hidden fields.
- The user selects a file and submits the form.
- The browser sends the
multipart/form-dataPOST request directly to the OVHcloud Object Storage endpoint. - OVHcloud validates the policy, verifies the signature, and stores the object.
- The browser receives a response: an HTTP redirect or a status code depending on your form configuration.
OVHcloud Object Storage supports the virtual-hosted style and the path style URL formats for POST uploads:
Replace <region> with the OVHcloud region identifier (for example: gra, rbx, sbg, bhs, de, uk).
Objects written via POST are immediately visible in the bucket (strong read-after-write consistency). The maximum object size per POST upload is 5 GB.
Configure bucket CORS
Browser POST uploads always trigger a CORS preflight (OPTIONS) request before any data is sent. Without a matching CORS rule on the bucket, the browser blocks the upload silently.
Save the following JSON to a file named cors.json:
Then apply it to your bucket:
Explanations:
--bucket <bucket_name>: replace with the name of your bucket.--cors-configuration file://cors.json: path to the CORS configuration file.
- Set
AllowedOriginsto the exact origin of your web application. Using*is accepted but not recommended in production. - Remove
"x-amz-version-id"fromExposeHeadersif versioning is not enabled on the bucket.
Generate the POST Policy
The POST Policy is a UTF-8 JSON document generated server-side. It defines the constraints that OVHcloud validates before accepting the upload. The document must be base64-encoded before being placed in the form.
Policy structure
Explanations:
expiration: mandatory ISO 8601 timestamp in GMT. The policy is rejected with HTTP 403 once this time has passed. Evaluated against the OVHcloud server time.conditions: every form field included in the request (exceptx-amz-signature,file, andpolicyitself) must have a matching condition in this array.content-length-range: restricts the accepted file size in bytes (here, 1 byte to 10 MB).
Condition types
Conditions
- The
${filename}variable in thekeyfield is substituted with the browser-supplied filename before policy validation. Use astarts-withcondition on$keyto restrict accepted filenames. - Fields prefixed with
x-ignore-are excluded from policy validation and are not stored on the object. - Unicode values must be escaped as
\uXXXX. Backslash\and dollar sign$characters must also be escaped. - OVHcloud normalises all form field names to lowercase before validation.
Calculate the SigV4 signature
The signature is computed server-side using HMAC-SHA256. The input to the signature is the base64-encoded policy document.
Step 1 - Encode the policy
Encode the policy JSON as a UTF-8 byte string, then base64-encode those bytes. The resulting string is both the policy form field value and the input to the signature (StringToSign).
Step 2 - Derive the signing key
Explanations:
<secret_key>: the secret access key of your Object Storage user.<date>: signing date inYYYYMMDDformat (for example:20260706). Must be within 7 days of the OVHcloud server's current date.<region>: OVHcloud region identifier (for example:gra,rbx,bhs). Must match the region used inx-amz-credential.- HMAC-SHA256 inputs and outputs are raw bytes, not hex strings, at every intermediate step.
Step 3 - Calculate the signature
The result is a lowercase hexadecimal string. Use this value as the x-amz-signature form field.
Build the HTML upload form
The upload form must use method="POST" and enctype="multipart/form-data". The action attribute must be the virtual-hosted bucket URL.
The file input field must be the last field in the form. Any fields placed after file are ignored by OVHcloud Object Storage.
Example form
Required form fields
Optional form fields
Total form data, excluding the file content, must not exceed 20,480 bytes (20 KB). Only one file may be uploaded per POST request.
Handle responses
Success responses
If success_action_redirect is set and the upload succeeds, the browser is redirected to that URL. The query parameters bucket, key, and etag are appended automatically. success_action_redirect takes priority over success_action_status when both fields are present.
OVHcloud enforces no domain restriction on the success_action_redirect target. Always restrict this field server-side when generating the form to prevent open redirect vulnerabilities.
Error responses
On failure, OVHcloud returns an S3-compatible XML error body:
Common error conditions:
Server-Side Encryption (SSE)
SSE-S3 - OVHcloud-managed key
To request server-side encryption with an OVHcloud-managed AES-256 key, add the following hidden field to the form:
Add the corresponding condition to the POST Policy:
If the bucket has a default SSE-S3 configuration, encryption is applied automatically without adding this field to the form.
SSE-C - customer-provided key
To encrypt the object with a key you provide, add the following three fields to the form. All three must have corresponding conditions in the POST Policy.
- SSE-C fields in the request take priority over any default SSE-S3 bucket configuration.
- With SSE-C, the returned
ETagis an opaque server-generated value and cannot be used for content integrity verification.
Versioning behaviour
The versioning state of the target bucket affects the upload response:
For more information, see the Object Storage - Getting Started with Versioning guide.
Go further
For training or technical assistance implementing our solutions, contact your sales representative or visit our Professional Services page to request a quote and have your project analysed by our experts.
Join our community of users.
1: S3 is a trademark of Amazon Technologies, Inc. OVHcloud's service is not sponsored by, endorsed by, or otherwise affiliated with Amazon Technologies, Inc.