Avatar background images and user profiles are examples of application features that developers use image uploads to scale. The project may sometimes be more significant in scope, such as a collection of photos accessible to the public or a developer's desire to learn about reactive systems.
This tutorial explains how to use Appwrite functions in reactive systems by creating an image upload and retrieval application. We will demonstrate how to select a picture from local storage, upload it to an Appwrite console, retrieve the list of all the images from the server, and update the UI.
Here is the link to the GitHub repository containing all the code.
To follow along with this tutorial, the following requirements apply:
- Xcode (with developer account for Mac users).
- Either IOS Simulator, Android Studio, or Chrome web browser — to run our application.
- Docker installation (recommended), DigitalOcean droplet, or Gitpod.
- An Appwrite instance. Check out this article for the setup.
- The user interfaces template. Here is a link to the repository containing the UI template.
To set up a project, we’ll type in the
host or IP address of our device in the browser to open an appwrite console. Then, click on
create project and give it a project name and ID (ID can be autogenerated).
In the home section of the Appwrite console, we will select
create platform, and in the popup, select Flutter. Within the Flutter section, choose
Android and input the
application name and package name (we can find them in our app-level
build.gradle file by heading to
Next, we want to set up a storage bucket. Head to the storage section and click on
add bucket. Then, we’ll set the
s read and write access to allow all users (role:all).
Finally, we want to create a database. To do so, we’ll navigate to the database section and click on
add database. Then, create a collection and set the
s read and write access to allow all users (role:all). We will also create a required string attribute to store the
URL of each image added to the storage.
In this section, we will need to clone the repository specified in the prerequisites. To do that, click on the link to the repository, and within the repository, click on
code and download it as a .zip file. To use the other methods, check out the GitHub docs on how to clone a repository.
Next, to utilize our Appwrite storage and database, we need to connect our Flutter project to the console. Doing this varies among devices. Thus, we will show the process of connecting to Android and iOS devices.
First, we will need to obtain the
bundle ID, which we can do by going to the
project.pbxproj file (
ios > Runner.xcodeproj > project.pbxproj) and searching for our
Now, we will head to the
Runner.xcworkspace folder in the applications iOS folder in the project directory on Xcode. Now, we want to select the runner target, and to do this; we will choose the Runner project in the Xcode project navigator and then find the Runner target. Next, select
IOS 11.0 in the
deployment info section as the target.
To do this, copy the
XML script below and paste it below the activity tag in the
Androidmanifest.xml file ( to find this file, head to
android > app > src > main).
Note: change [PROJECT-ID] to the id you used when creating the Appwrite project
The cloned repository contains an
authprovider folder, the
homepage.dart file, and the
main.dart file in the
lib folder. When we run it, we should have a UI that looks like the image below:
As we can see above, there are two buttons (
select file and retrieve) and a display area that shows the images uploaded to the database in a grid format. Currently, the template lacks functionality; thus, we will work on that in the coming sections.
Before we begin, we will need to add the following dependencies to the
- provider: ^6.0.3
- file_picker: ^4.5.1
- appwrite: ^6.0.0
Next, within the lib folder, we will create two different folders; constants and models. In the constant folder, we will create a file called
app_constants.dart and will add the code below to the file:
To get the
IP address for a physical emulator, we will connect our device running the Appwrite instance and physical emulator to the same wifi device and type the command below in the terminal:
The command above will bring out the IPs of the devices connected to our PC.
Creating the image upload feature
We will need to create a model class to convert the response received when we send a file to the Appwrite storage bucket. We do this because, unlike the web SDK, Appwrite does not return a link when getting a file preview. Thus, we will have to create a URL manually for every file added to the storage bucket, and we will need two data (
Now, within the
model folder, we will create a file called
fileurl.dart and add the code below to it:
The code above creates a class called
UploadedFiles with some required properties followed by some constructors. It then creates a
toJson method for serialization.
To create our application's core logic, we will update the code in the
imageprovider.dart file in the template. Using the
provider package, we can affect the state of our UI. Before we can do that, we need to update the
imageprovider.dart file with the code below:
In the code above, we have a
ChangeNotifier class. Within it, we called the
Appwrite client, account, storage API, a
PlatformFile (from the
file_picker package), and also the model class we created earlier. Next, we called a
getter for the model class and created a function called
_initialize(). Within the
_initialize() function, we set the
_uploadedFiles to null (initializers), initialize the Appwrite's API, and call the
_getaccount function, which conditionally creates an
anonymous user session.
Next, we will use the
file_picker package within the
filepicker function to select image files from our device storage. The function calls the
Filepicker method and checks whether it returns null. If false, it will return the
As specified in the code above, we will need to create a function called
_uploadfile(). After picking the file, we’ll use the
Appwrite storage API to get the image selected by the path and upload it to the file bucket within our Appwrite storage. We will then check if the
id is present, and if true, we will map the value of the uploaded image file to the model class; if false, we do nothing.
Creating the image retrieval feature
Now that we can upload images to the server, we want to be able to get the image from the Appwrite server. As mentioned earlier, we created a model class to manually create a
URL. Before we delve into that aspect, we will need to create a model class to map the data sent to the database.
Now, we will call the Appwrite database API and the model class we created above, followed by a
getter for the model class. Next, we will initialize the database API and call the
createdocument() function in the
filepicker function (add it before
createdocument() will handle uploading the URL we created to the database.
createdocument() function contains a manually created URL generated from an interpolation of other data stores (variables, constants, model classes), and here is how it looks:
After, we will call the
createDocument method from the Appwrite database function and set the data key and value pair to the attribute name created in the collection and our manually created
Finally, we will create a future asynchronous function that will list the documents in our collection and map them to the model class
Consuming the service
We want to use some of the functions from our
ChangeNotifier class within our UI. On the
homepage.dart file of the UI template, we wrapped the body property in a
Consumer class (from the provider library). Thus, we can call functions and getters from the
ChangeNotifier class to the UI. Thus, we will set the value of the
NetworImage as below:
image: NetworkImage( state.docmodel![index].url!) ),
Finally, here is how our application looks:
In this tutorial, we created an Appwrite service to store uploaded image files, built custom URLs for each uploaded image using the File list object, created a database collection for the URL, and retrieved the URL to map it to the user interface. Here are some related resources you might find useful”
Thanks for reading, and happy coding!