Why an S3 Upload Can Work While the Browser Preview Fails

A successful server-side upload does not prove that a browser can preview the same file. These are separate requests with different security rules.

Why it happens

An application can upload a file to S3-compatible object storage and still appear to hang when it tries to show the preview. The upload may already be complete. The browser preview can fail because the storage bucket does not allow the website origin through Cross-Origin Resource Sharing, usually called CORS.

Why the two tests behave differently

A command-line or server-side storage test sends the file from the application server to object storage. Browser CORS rules do not apply to that request.

A preview component often uses JavaScript to fetch the stored image. That request travels from the user’s browser to a different origin. The browser checks the response for an allowed origin before letting the page use the file.

This also explains why opening the image directly in a new tab may work. Direct navigation can display the file, while a JavaScript fetch from another origin still requires CORS permission.

How to diagnose it

  1. Confirm that the object exists in storage after the upload attempt.

  2. Open the browser developer tools and inspect the failed preview request.

  3. Look for an error mentioning Access-Control-Allow-Origin or a blocked cross-origin request.

  4. Compare the request origin with the bucket’s allowed origins.

  5. Test again after updating the bucket configuration and refreshing the page.

What the bucket usually needs

For a read-only image preview, the bucket normally needs to allow the exact application origin and the GET and HEAD methods. The origin must include the correct scheme and hostname, without an extra path.

If direct browser uploads are also used, the existing rule may need additional methods and headers. Extend the current rule carefully instead of replacing unrelated permissions.

Common mistakes

  • Cause: Testing only with a server console. Fix: Test the actual browser preview request too.
  • Cause: Adding CORS headers to the application server. Fix: Configure the object-storage bucket that serves the file.

  • Cause: Allowing the wrong origin. Fix: Copy the exact origin shown in the browser error.

  • Cause: Assuming a successful new-tab view proves CORS works. Fix: Check the JavaScript fetch response headers.

CORS does not grant access to a private object

Keep bucket permissions and signed-URL authentication separate from CORS. A response can have correct CORS headers and still return 403 because a signature expired or the caller lacks permission. Do not make a private bucket public to repair a preview. Inspect both the status code and response headers.

Treat upload, storage, and preview as separate stages. The next action is to inspect the browser’s failed request before changing application code; if the object exists and the console reports an origin error, fix the bucket CORS rule.

Reference: Amazon S3 CORS documentation.

Leave a Reply