devin
March 3, 2025, 8:31pm
1
I am using <Dropzone />
for uploading image and want to display the image once the user inputs. However, this is not supported.
<Image source={URL.createObjectURL(file)} />
Safari: Not allowed to load local resource: blob
Firefox: Security Error: Content at https://shopify.com/123/account/pages/456
may not load data from blob:https://extensions.shopifycdn.com/567.
I believe this is CORS and can be tweaked?
Hey @devin , this is a known issue at the moment caused by the blob: url belonging to a different origin.
I think you have two options.
Upload the image somewhere and use that URL as source for your Image
.
Convert the file content to a data url and pass this as source
function YourComponent() {
const [image, setImage] = useState(null);
<>
<DropZone
onInput={([file]) => {
const reader = new FileReader();
reader.onloadend = () => {
const dataUrl = reader.result;
setImage(dataUrl);
};
reader.readAsDataURL(file);
}}
></DropZone>
{image ? <Image source={image} /> : null}
</>
}
1 Like
devin
March 3, 2025, 9:50pm
3
Thank you. For some reason I’m struggling to get the react state working with “multiple” input setup so I may have to go with single.
@devin do you mind sharing the code that you’re struggling with?
devin
March 3, 2025, 10:43pm
5
This code isn’t perfect but represents the effort. I’ll likely get back to it later this week because I need multiple to work well.
<DropZone multiple onInput={(files) => {
files.forEach((file) => {
const reader = new FileReader();
reader.onloadend = () => {
const dataUrl = reader.result as string;
setFiles({ ...files, ...{ [file.name]: dataUrl } });
};
reader.readAsDataURL(file);
})
}} />
{files.map(file => <Image source={file.dataUrl} />)}
devin
March 4, 2025, 8:52pm
6
Alright @Robin-Shopify I got it working with this
onInput={async (files) => {
const newFiles: (File & { dataUrl?: string })[] = [];
await Promise.all(files.map(async (file) => {
const dataUrl = await new Promise<string>((resolve) => {
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result as string);
reader.readAsDataURL(file);
});
newFiles.push({
...file,
dataUrl,
// can't spread because these File object properties are not enumerable
name: file.name,
size: file.size,
type: file.type,
lastModified: file.lastModified
});
}));
1 Like