Scale up as you grow — whether you're running one virtual machine or ten thousand.

From GPU-powered inference and Kubernetes to managed databases and storage, get everything you need to build, scale, and deploy intelligent applications.

This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.
Hi there,
From what I have seen, this is expected behavior with DigitalOcean Spaces and presigned URLs. When you add ACL: 'public-read', the presigned URL typically expects the x-amz-acl header to be part of the request. From the browser side, that usually turns the upload into a non-simple CORS request, which then triggers a preflight OPTIONS check.
Even if your CORS config allows *, in practice you may still need to explicitly allow x-amz-acl in the Spaces CORS settings and make sure PUT and OPTIONS are listed as allowed methods. Otherwise the browser can block the upload before it reaches Spaces.
Two approaches that often work:
You can keep using public-read, but update your Spaces CORS config to explicitly include x-amz-acl in Allowed Headers.
Or you can upload the object as private (no ACL in the presigned URL) and then make it public afterward from the server side or via a public bucket. That tends to avoid most CORS edge cases in the browser.
So while there could be a few moving parts here, depending on the client and SDK, the x-amz-acl header requirement is usually the main trigger for this kind of CORS error.