DEV Community

loading...
Cover image for #30DaysofAppwrite : File Uploads and Downloads
Appwrite

#30DaysofAppwrite : File Uploads and Downloads

Damodar Lohani
・4 min read

Intro

Appwrite is an open-source, self-hosted Backend-as-a-Service that makes app development easier with a suite of SDKs and APIs to accelerate app development. #30DaysOfAppwrite is a month long event focused on giving developers a walkthrough of all of Appwrite's features, starting from the basics to more advanced features like cloud functions! Alongside we will also be building a fully featured Medium Clone to demonstrate how these concepts can be applied when building a real world app. We also have some exciting prizes for developers who follow along with us!

File Uploads and Downloads

Uploading files, previewing images, and downloading files is super easy using Appwrite's Storage API. As we learned before, the Storage API also provides options to manipulate images and display previews.

In today's session we will look into how we can leverage that to add cover images to our blog posts. Based on whether we are viewing the details of a post or just listing the post, we can crop the image thumbnail to an appropriate size to display as the preview. Let's learn how.

New Post Component

First we will modify the new post component src/routes/Create.svelte to add a File input field above the title field.

<label for="cover">Cover</label>
<input type="file" bind:files />
Enter fullscreen mode Exit fullscreen mode

Then we will modify the submit function in the scripts section of the same file to handle the files input.

let cover;

const submit = async () => {
    //...code before
    if (files && files.length == 1) {
        let file = await api.uploadFile(files[0], $state.user.$id);
        cover = file.$id;
    }
    //... code after
}
Enter fullscreen mode Exit fullscreen mode

Now we need to create an uploadFile() function in src/appwrite.js.

export const api = {
    //...existing code
    uploadFile: (file, userId) =>
        sdk.storage.createFile(file, ["*"], [`user:${userId}`]),
}
Enter fullscreen mode Exit fullscreen mode

Now, when editing the post the files have to be handled. If user uploads new cover image, we delete the old one and upload the new one. So first let's add deleteFile() function in src/appwrite.js.

export const api = {
    //...existing codes
    deleteFile: (id) => sdk.storage.deleteFile(id),
}
Enter fullscreen mode Exit fullscreen mode

Also, modify the submit function in src/routes/Create.svelte to handle deleting while editing.

const submit = async () => {
    //...code before
    if (files && files.length == 1) {
        if(params.slug) {
            await api.deleteFile(cover);
        }
        let file = await api.uploadFile(files[0], $state.user.$id);
        cover = file.$id;
    }
    //... code after
}
Enter fullscreen mode Exit fullscreen mode

Image Preview

Appwrite's storage API provides an easy way to generate preview thumbnails using its simple rest API. Let's create a method called getThumbnail in src/appwrite.js that will generate the thumbnail for our blog post with appropriate size.

getThumbnail: (id, width = 1000, height = 600) =>
    sdk.storage.getFilePreview(id, width, height),
Enter fullscreen mode Exit fullscreen mode

The above function will generate the image thumbnail with the provided width and height.

Now we will use that function to display the image in our index component, post preview component, and the user's own post preview component.

First, in src/routes/Index.svelte under promoted and featured section, let's add the image preview if the cover image exists.

Promoted post

<div class="promoted">
    {#if promoted.cover}
        <img src={api.getThumbnail(promoted.cover)} alt="" />
    {/if}
    <h2>{promoted.title}</h2>
    <Author user={promoted.user_id} />
    <p>
        {@html md(promoted.text)}
    </p>
    <Action href={`#/post/${promoted.$id}`}>Read more</Action>
</div>
Enter fullscreen mode Exit fullscreen mode

Featured post

<a class="card" href={`#/post/${feature.$id}`}>
    {#if feature.cover}
        <img
            src={api.getThumbnail(feature.cover, 600, 400)}
            alt="" />
    {/if}
    <h2>{feature.title}</h2>
</a>
Enter fullscreen mode Exit fullscreen mode

Let's modify the src/lib/Preview.svelte also to show the cover image

<a href={`#/post/${post.$id}`}>
    {#if post.cover}
        <img
            class="cover"
            src={api.getThumbnail(post.cover, 400, 250)}
            alt="" />
    {/if}
    <h2>{post.title}</h2>
</a>
Enter fullscreen mode Exit fullscreen mode

Similarly, modify the src/lib/MyPost.svelte also to show the cover image

<article class="card">
    {#if post.cover}
        <img
            class="cover"
            src={api.getThumbnail(post.cover, 400, 250)}
            alt="" />
    {/if}
    <h2>{post.title}</h2>
    <a href="/post/{post.$id}" use:link class="button">Preview</a>
    <a href="/post/{post.$id}/edit" use:link class="button">Edit</a>
    <a
        href="/delete"
        on:click|preventDefault={() => deletePost(post.$id)}
        class="button">Delete</a>
</article>
Enter fullscreen mode Exit fullscreen mode

Finally, modify the src/routes/Post.svelte as well

<h1>
    {post.title}
</h1>
<Author user={post.user_id} />
{#if post.cover}
    <img class="cover" src={api.getThumbnail(post.cover)} alt="" />
{/if}
<section class="content">
    {@html md(post.text)}
</section>
Enter fullscreen mode Exit fullscreen mode

That's how easy it is to upload files and display image thumbnails of different sizes using Appwrite - no need to use any external libraries. Once generated, the thumbnails are cached in the server, so the responses are super fast at runtime.

Credits

We hope you liked this write up. You can follow #30DaysOfAppwrite on Social Media to keep up with all of our posts. The complete event timeline can be found here

Feel free to reach out to us on Discord if you would like to learn more about Appwrite, Aliens or Unicorns 🦄. Stay tuned for tomorrow's article! Until then 👋

Discussion (1)

Collapse
juanfrank77 profile image
Juan F Gonzalez

How beautiful that you chose Svelte for this examples.