How To Upload Files To Supabase Storage Buckets and Write Data To Supabase Using Remix
Tags: remix, supabase, react, video
Published: 2021-12-31 04:07:57

> **Update:** Source code updated 05/22/2022 to version 1.5.1 of remix-run

---

### Overview
Simple application showing file upload and writing database records using [Remix](https://remix.run/docs/en/v1) and [Supabase](https://supabase.com/docs/)

We show how Actions and Loaders work to manager working with server for data and to make API calls. In both of the examples presented in video, the actions are processing the form data and then making the appropriate calls to Supabase. We then take the responses we get from [Supabase](https://supabase.com/docs/) and populate action data which is returned to the page and rendered appropriately.

>[Remix](https://remix.run/docs/en/v1) is a full stack web framework that lets you focus on the user interface and work back through web fundamentals to deliver a fast, slick, and resilient user experience.

### The Video
{% youtube ySQcGc9NICo %}

### Writing Data
This is the action function related to writing new record to the database. The form that is being processed has an input elements for all of the fields to be written to database. On successful write to database, we redirect back to the default route of application

- [Using Supabase Database, Built On Posgres](https://supabase.com/docs/guides/database)

```react
export const action = async ({ request }) => {
  // get data from form
  let form = await request.formData();
  let name = form.get("name");
  let description = form.get("description");
  let state = form.get("state");

  // use form information to write to supabase
  const { data, error } = await supabaseClient
    .from("chargers")
    .insert([{ name, description, state }]);

  // if no error, back to home page... index.jsx
  if (!error) {
    return redirect("/", {});
  }

  // else stay on page and return error information
  return { data, error };
};
```

### Uploading Files
> Currently a bug in Remix when uploading large files. In this example I am only using small files to show how the process works

This example is derived from the Remix documentation on `uploadHandler` which can be found [here](https://remix.run/docs/en/v1/api/remix#uploadhandler)

### Access To Storage Buckets
[Creating buckets in Supabase]() is beyond the scope of this video, you can read more here, but I wanted to include the script for creating the appropriate policy because I got stuck on this issue.

This is the SQL script I used to allow you to upload files to Supabase Storage. I am not restricting access for the purpose of this demo but you can read up more or on creating policy here in the [Supabase Documentation]()

> replace my bucket id "images" with the name of your bucket

```sql
create policy "ALL images are publicly accessible."
  on storage.objects for select
  using ( bucket_id = 'images' );

create policy "Anyone can upload an image."
  on storage.objects for insert
  with check ( bucket_id = 'images' );

create policy "Anyone can update an image."
  on storage.objects for update
  with check ( bucket_id = 'images' );
```

This is the action function related to file upload. The form that is being processed has an input element with the id `my-file`

- [Using Supabase Buckets](https://supabase.com/docs/guides/storage)

```react
export const action = async ({ request }) => {
  try {
    /**
     *
     * @param {*} param0
     * @returns
     */
    let uploadHandler = async ({ name, stream, filename }) => {
      console.log("in uploadHandler");

      if (name !== "my-file") {
        stream.resume();
        return;
      } else {
        console.log(name, filename);
      }

      // Get the file as a buffer
      const chunks = [];
      for await (const chunk of stream) chunks.push(chunk);
      const buffer = Buffer.concat(chunks);

      // call supabase function for uploading to bucket
      const { data, error } = await supabaseClient.storage
        .from("images")
        .upload(filename, buffer);
      if (error) {
        throw error;
      }

      // return information up uploaded file
      return JSON.stringify({ data });
    };

    // get file info back after image upload
    const form = await unstable_parseMultipartFormData(request, uploadHandler);

    //convert it to an object to padd back as actionData
    const fileInfo = JSON.parse(form.get("my-file"));

    // this is response from upload handler
    console.log("the form", form.get("my-file"));

    // return success action data
    return fileInfo;
  } catch (e) {
    // return error action data
    return { error: e };
  }
};
```