0

In my next.js app I am trying to upload image from form. But I keep getting an error: [Error] Unhandled Promise Rejection: TypeError: Load failed And the file doesn't upload to supabase.

I checked the image variable via console, it is a File object. Here is how I do it, I followed the tutorial in documentation:

import * as Form from "@radix-ui/react-form";
import { createClient } from "@supabase/supabase-js";

const supabase = createClient(
  "url",
  "api-key",
);

export default function Warehouses() {

  async function uploadImage(e) {
    const image = e.files[0];

    const { data, error } = await supabase.storage
      .from("images")
      .upload("/", image);

    if (data) {
      console.log(data);
    } else {
      console.log(error);
    }
  }

  const onSubmit = (event) => {
    uploadImage(event.target.images);
  };

  return (
    <div>
        <Form.Root className="FormRoot" onSubmit={onSubmit}>
          <Form.Field className="FormField" name="images">
            <div
              style={{
                display: "flex",
                alignItems: "baseline",
                justifyContent: "space-between",
              }}
            >
              <Form.Label className="FormLabel">
                Upload Images
              </Form.Label>
            </div>
            <Form.Control asChild>
              <input
                type="file"
                id="images"
                name="images"
                multiple
              />
            </Form.Control>
          </Form.Field>

          <Form.Submit asChild>
            <Button>Create</Button>
          </Form.Submit>
        </Form.Root>
    </div>
  );
}

I will appreciate any help!

UPDATE

I get this error in Safari browser also:

[Error] Fetch API cannot load https://my-url/storage/v1/object/images/2 due to access control checks.

Here is what I get from console.log(image) inside uploadImage(): image variable

I also tried to check the connection to supabase with this code:

export async function getServerSideProps() {
  const buckets = await supabase.storage.listBuckets();
  console.log(buckets);
  
  return {
    props: {
      bucketList: buckets,
    },
  };
}

But I get this in the console: ``` { data: [], error: null } ``

Below are the policies to my supabase bucket "images":

enter image description here

Here is the first (select) policy edit window: enter image description here

And the insert policy: enter image description here

Here is how the policies were added to my bucket:

enter image description here

enter image description here

1 Answers1

1

You are not uploading the file in a way that passes the insert policy you have in place.

The issue is that you have the storage.foldername(name)[1] = 'public', but you are not uploading the image in a public folder. For this poilcy to pass, you need to upload the image into /public path instead of /. I assume what you meant here is that you are uploading an image to a public bucket, but that is different from uploading to a public path. I think you can remove the storage.foldername(name)[1] = 'public' statement.

Also, there are other things you can remove as well. First, we recently added a feature to restrict the meme types of the object being uploaded to a bucket. You can set it like this to only accept jpg.

restrict meme types

About the role, the correct way to specify which role you want the policy to be applied to is to select the target roles from the policy editor. You can set this to anon to target anon users.

With all of that, you should be left with the following simple policy for what you want to do.

insert policy

Note that having users sign in to your app is not essential, but might be something to consider before you start promoting your app, because otherwise anyone can upload images to your bucket without any restrictions.

dshukertjr
  • 15,244
  • 11
  • 57
  • 94
  • Thank for such a detailed response and for the additional advices! I will add authentication in future. I deleted all the policies and added two for select and for insert as you wrote. Unfortunately, the issue stays. I still get "TypeError: Load Failed". Is it something with my policies or could there be some else reasons? – Даниэль Сеидов May 01 '23 at 15:44
  • I also tried adding this code inside uploadImage() to check if I can get access my buckets: ```const abc = await supabase.storage.listBuckets(); console.log(abc);``` in console I get: ```{data: [], error: StorageUnknownError: Load Failed}``` – Даниэль Сеидов May 01 '23 at 15:47
  • It finally worked after I provided the name of the image! Thanks a lot for your help, the problem was in policies. So now it is something like this: ```const { data } = await supabase.storage.from("images").upload(`/${filePath}/${image.name}`, image);``` – Даниэль Сеидов May 02 '23 at 00:00
  • 1
    @ДаниэльСеидов Oh yeah, missed that part! Also, the reason why you are not getting any buckets from `listBuckets()` is because you don't have any policies set on buckets. You typically don't want to expose bucket information publicly, so I suggest to keep not having any policies for the buckets though. – dshukertjr May 02 '23 at 01:23