DEV Community

Cover image for Flutter Apps with AWS Amplify Backend: Part 4 — Storage
FlutterArticles
FlutterArticles

Posted on • Edited on

Flutter Apps with AWS Amplify Backend: Part 4 — Storage

Flutter Apps with AWS Amplify Backend: Part 4 — Storage

Manage user content using Amazon S3

What is Amplify Storage?

The Amplify Storage category provides an interface for managing user content for your app in […] storage buckets. The Storage category comes with default built-in support for Amazon Simple Storage Service (S3).

NOTE: Amplify Flutter is still in developer preview and is not recommended for production use at this time.

What Will We Be Making?

In this tutorial, we will be creating a simple application that uses the basic features of Amplify Storage. We will be able to upload an image, download it, and delete it using the Amplify API.

Example Usage of AppExample Usage of App

Prerequisites

The only thing you need for this tutorial is the app you created in Part 1 of this tutorial series.

If you don’t want to read part 1 and you are already familiar with Amplify Flutter, then simply create a new Flutter application and connect it to a cloud instance of Amplify.

Let’s Dive In

Create a Basic Amplify Project

If you are using the app you created in Part 1, you can skip this step.

Otherwise, create a new flutter project, and from the project directory run:

amplify init
Enter fullscreen mode Exit fullscreen mode

Setup the Backend

The backend can be set up entirely through the amplify cli:

amplify add storage
Enter fullscreen mode Exit fullscreen mode

Follow the setup wizard to add storage to your applicationFollow the setup wizard to add storage to your application

Checking on our resources

To check on our project’s cloud resources, run:

amplify console
Enter fullscreen mode Exit fullscreen mode

This will launch your project’s console in your browser.

Authentication and File storage are configured for our projectAuthentication and File storage are configured for our project

Integrate Storage Features

Add the amplify packages to your pubspec.yaml.

dependencies:
  file_picker: '^1.8.0+1'
  amplify_core: '<1.0.0'
  amplify_auth_cognito: '<1.0.0'

  amplify_storage_s3: '<1.0.0'
Enter fullscreen mode Exit fullscreen mode

Next, include the necessary packages in your main.dart file:

import 'package:file_picker/file_picker.dart';
import 'package:amplify_core/amplify_core.dart';
import 'package:amplify_storage_s3/amplify_storage_s3.dart';
import 'package:amplify_auth_cognito/amplify_auth_cognito.dart';
Enter fullscreen mode Exit fullscreen mode

Initializing Amplify Storage

If you don’t want to be bored with the specifics of setting up this application from scratch, take a look at the gist here or the repo for the completed code.

First, let’s set up a barebones main.dart for you to work with:

import 'package:amplify_auth_cognito/amplify_auth_cognito.dart';
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:amplify_core/amplify_core.dart';
import 'package:amplify_storage_s3/amplify_storage_s3.dart';
import 'amplifyconfiguration.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  bool _isAmplifyConfigured = false;
  String _uploadFileResult = '';
  String _getUrlResult = '';
  String _removeResult = '';
  Amplify amplify = new Amplify();

  @override
  void initState() {
    super.initState();

    configureAmplify();
  }

  void configureAmplify() async {
    // First add plugins (Amplify native requirements)
    AmplifyStorageS3 storage = new AmplifyStorageS3();
    AmplifyAuthCognito auth = new AmplifyAuthCognito();
    amplify.addPlugin(authPlugins: [auth], storagePlugins: [storage]);

    // Configure
    await amplify.configure(amplifyconfig);

    setState(() {
      _isAmplifyConfigured = true;
    });
  }

  void _upload() async {
  }

  void getUrl() async {
  }

  void _download() async {
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Amplify Flutter Storage Application'),
        ),
        body: Center(
          child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
            RaisedButton(
            onPressed: _upload,
            child: const Text('Upload File'),
          ),],

          ),
        ),
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

As always, we want to configure our Amplify plugin. The only thing different between the previous tutorials is which plugins we will be adding. In this case, we want both AmplifyStorageS3 and AmplifyAuthCognito.

Uploading Files

To upload a file from your computer to your emulated device, simply drag and drop a file over the emulator.

You will also need to implement your _upload() function as follows:

  void _upload() async {
    try {
      print('In upload');
      File local = await FilePicker.getFile(type: FileType.image);
      final key = 'ExampleKey';
      Map<String, String> metadata = <String, String>{};
      metadata['name'] = 'vennify_logo';
      metadata['desc'] = 'A photo of the vennify logo';
      S3UploadFileOptions options = S3UploadFileOptions(
          accessLevel: StorageAccessLevel.guest, metadata: metadata);
      UploadFileResult result = await Amplify.Storage.uploadFile(
          key: key, local: local, options: options);
      setState(() {
        _uploadFileResult = result.key;
      });
    } catch (e) {
      print('UploadFile Err: ' + e.toString());
    }
  }
Enter fullscreen mode Exit fullscreen mode

This will upload a file to the cloud with the key ‘ExampleKey’ which we can use later to download or interact with the file.

‘ExampleKey’ file (our logo image) has been successfully added to our bucket‘ExampleKey’ file (our logo image) has been successfully added to our bucket

Downloading Our File

Okay, so we have a file now in our S3 bucket. Let’s say we want to render this image in our app. There are a couple of ways to do this, but for now, I will show you the easier of the two.


  void _getUrl() async {
    try {
      print('In getUrl');
      String key = "ExampleKey";
      S3GetUrlOptions options = S3GetUrlOptions(
          accessLevel: StorageAccessLevel.guest, expires: 10000);
      GetUrlResult result =
      await Amplify.Storage.getUrl(key: key, options: options);

      setState(() {
        _getUrlResult = result.url;
      });
    } catch (e) {
      print('GetUrl Err: ' + e.toString());
    }
  }
Enter fullscreen mode Exit fullscreen mode

The _getUrl() *function basically searched through our S3 bucket for a file with the key ‘ExampleKey’ and fetches the URL for this file. Using this URL, we can then load the image. In our example, once the URL is fetched, *setState() *is called, which rebuilds a *NetworkImage in our widget tree, thus displaying our photo.

Don’t forget to add a button that executes *getUrl() *when pressed. You can always take a look at the repo if you are just interested in the completed code.

Pretty cool right? In your implementation, you may want to obtain the key (in this case it is hardcoded as ExampleKey) differently.

Deleting Files

Deleting files is very similar to uploading them. Like most of these storage functions, you interact with your files based on their key. Therefore, to delete a file in your bucket you just need its key.


  void remove() async {
    try {
      String key = "ExampleKey";
      RemoveOptions options =
      RemoveOptions(accessLevel: StorageAccessLevel.guest);
      RemoveResult result =
      await Amplify.Storage.remove(key: key, options: options);

      setState(() {
        _removeResult = result.key;
      });
      print('_removeResult:' + _removeResult);
    } catch (e) {
      print('Remove Err: ' + e.toString());
    }
  }
Enter fullscreen mode Exit fullscreen mode

Moving Forward

Congratulations! You now have covered all of the basics of storage using S3, and if you have read the other parts of this series, you have also dabbled with Analytics using Pinpoint and Authentication with Cognito.

Now that we have the basics pinned down, future articles will feature a combination of these services to create more fully-featured applications.

This Series

Part 1: Basic Setup

Part 2: Authentication

Part 3: Analytics

Part 4: Storage

Top comments (0)