Public image libraries such as Unsplash have been a breath of fresh air for content creators, enabling access to tons of copyright-free images. Sometimes, though, creators prefer privacy content and want to gatekeep "good" things. This article covers how to securely upload private images to Appwrite using Flutter.
This article demonstrates the following:
- User registration and login using Appwrite
- State management using the provider package in Flutter
- Picking images from storage using the
file_pickerpackage in Flutter and uploading the images to Appwrite
- Setting document-level permission within Appwrite
- Obtaining the images from Appwrite and updating the UI
If you want to jump straight into the project, you can clone the repository containing the code for the project.
The following requirements apply to follow along:
- Xcode (with developer account for Mac users).
- Either iOS Simulator, Android Studio, or Chrome web browser — to run your 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.
Setting up the Appwrite project
After setting up an Appwrite instance, head to your browser and type in your
IP address or
hostname. Next, select
Create Project and fill in your desired
project name and
Note: ID can be auto-generated
After creating a project, scroll down within the Appwrite console and select
create platform. When you get a popup, select
Flutter and choose the operating system you plan to work on
(in this case, choose
Android). Next, specify the
package names (you can find the packaging in your app-level
After creating a platform, head to storage to create a bucket. To do that, click on
add bucket, then set the bucket-level permission's read and write access to allow all users (
Unlike the other client-side SDKs, the Flutter SDK does not return a URL when previewing a storage file from Appwrite. In this tutorial, you will use a database to store the URL of every new image file upload. Head to the database section and select
Next, we’ll create a collection. When allowing public access to a collection, use collection-level permissions, preferably the permission
role:all. In this case, use document-level permission, as this allows all the users to share a single collection, but they have access to their documents only. Now, let’s create a required string attribute called
url to store the manually generated URL of each image added to the storage.
Cloning the Flutter UI template and connecting to Appwrite
This section uses a UI template containing user registration and login code. To get it, clone the repository specified in the prerequisites. Check out the official GitHub docs to learn more about cloning a repository.
If you're not new to Appwrite, you can proceed to the next step, but for new readers, this is how to connect a Flutter project to Appwrite for Android and iOS devices.
First, obtain the
bundle ID by going to the
project.pbxproj file (
ios > Runner.xcodeproj > project.pbxproj) and searching for the
Now, head to the
Runner.xcworkspace folder in the applications iOS folder in the project directory on Xcode. To select the runner target, choose the Runner project in the Xcode project navigator and then find the
Runner target. Next, select
General and 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
When you run the cloned repo, you should have a UI that looks like the image below:
Above is a homepage section with an elevated button that satisfies multiple commands depending on the condition. These conditions range from checking if a user is logged in and redirecting you to a login page if
false to selecting an image(s) from your local storage, uploading it to Appwrite, and displaying the images in a grid.
Currently, the template lacks most of the functionality mentioned above. Thus, start by updating two folders (constants and model) within the lib folder with some new files. Starting with the constants folder, create a file called
app_constants.dart, which is required to store some constants that you will use later. Start by pasting the code below into the file:
Next, we’ll create two model classes similar to the one in the template folder. Let’s use the first model class to map out the structure of the storage bucket, as we’ll manually create a URL. Thus, there are two essential data from every newly uploaded file: the
bucketID and the
uploaded file's ID.
To use the model class above, we need to be able to pick a file from your local storage and upload it to Appwrite. Thus, head to the
privateprovider.dart file and call the Appwrite
storage API, the model class created earlier, and a
PlatformFile class from the
file_picker package within the
Next, create a getter for the model class, then set the value for the model class and the
PlatformFile class to null(initializers). Also, remember to initialize the Appwrite's storage API. Next, create a function to select images from local storage and call it within the conditional statement in the
Next, create a function to upload the selected file from the local storage to the Appwrite storage bucket. In the function, we’ll need to map the
JSON result to the model class using the
jsonDecode functions provided by the
dart convert package. Finally, call the function within the
filepicker function, and it should look like this:
To retrieve the images from the storage bucket, we need to use the database created earlier and create another model class to map the list of documents from the database. Thus, a model class like the one below is required:
Next, call the Appwrite database API and the model class above. Then, create a getter for the model class and initialize the database API.
After uploading the image to a storage bucket, we’ll "convert" the image into a URL. To do that, create another function, and within the function, create a variable with the value of a
query string created from using the endpoint,
projectid. Next, initialize the Appwrite database
createDocument method and set the data to the variable you created. Call the function in the file picker function so it can trigger the function automatically after uploading the files to the storage bucket.
Now, we’ll create another function to display the images using the
listDocuments method from the database function. Then map through the list of documents with respect to the model class created earlier. For this section, we need to be able to display the images once a user logs in or once they upload a new image. Thus, call the function in the
Now, the provider is ready for use, and all that is left is updating the
home.dart file with the code below:
The code above consists of a button that triggers a function linked to the
checklogin function within the
ChangeNotifier class (
PrivateProvider). The body uses a
GridView.builder, which creates a grid of containers with respect to the number of items in a list. In this case, it is the list of documents in the database. The containers are decorated using a
NetworkImage using the URL value obtained from the database collection.
This article explains how to use the Appwrite service to register and log in users as well as how to create document-level access to allow users to have permission to access documents particular to them alone. Using that idea, we’ve built a private image upload using the
filepicker package and Appwrite.
For further reading, here is a resource you might find helpful:
Top comments (0)