Skip to content

Blob Storage

Freestyle doesn’t provide a new blob storage API, it simply allows you to store the builtin JavaScript Blob class in your data. Behind the scenes freestyle is extracting the blobs from your data and storing them separately from the rest of your data.

Let’s build an example. Let’s say you want to allow users to upload images to your site.

@cloudstate
class Image {
id = crypto.randomUUID();
blob: Blob;
name: string;
constructor(name: string, blob: Blob) {
this.name = name;
this.blob = blob;
}
}
class App {
static id = "app";
images: Image[] = [];
uploadImage(options: { name: string; blob: Blob }) {
const image = new Image(options.name, options.blob);
this.images.push(image);
return {
id: image.id,
};
}
}

To expose images to the frontend, we’ll need to implement a special method called fetch. Fetch allows you to define how a class should behave to a rest API. In this case, we’ll use it to allow the browser to download the image.

@cloudstate
class Image {
// ...
async fetch(_request: Request) {
return new Response(await this.blob.arrayBuffer(), {
headers: {
"Content-Type": this.blob.type,
"Content-Length": this.blob.size.toString(),
},
});
}
}

We’ll also implement a method for our convenience that returns the url to this class instance. Note that this URL is not user configurable, this is the URL that cloudstate instances will be served from.

@cloudstate
class Image {
// ...
getUrl() {
return `/cloudstate/instances/${this.id}`;
}
}

Let’s also add a method to our App class that returns the url and name of all the images.

@cloudstate
class App {
// ...
getImages() {
return this.images.map((image) => ({
name: image.name,
url: image.getUrl(),
}));
}
}

And then finally, we can display the images in our frontend.

import { useCloud } from "freestyle-sh";
import type { App, Image } from "./app.ts";
const app = useCloud<typeof App>("app");
const images = await app.getImages();
export function AppPage() {
return (
{images.map((image) => (
<img src={image.url} alt={image.name} />
))}
);
}