Flutter AWS S3存储管理插件amplify_storage_s3的使用

发布于 1周前 作者 yibo5220 来自 Flutter

Flutter AWS S3存储管理插件amplify_storage_s3的使用

插件简介

amplify_storage_s3 是Amplify Flutter Storage类别的插件,它使用AWS S3作为提供者。此插件支持Android、iOS、Web、Windows、MacOS和Linux平台。

平台支持情况

Category Android iOS Web Windows MacOS Linux
Analytics
API (REST)
API (GraphQL)
Authentication
DataStore 🔴 🔴 🔴 🔴
Storage
Notifications 🔴 🔴 🔴 🔴

注:✅ 表示支持,🔴 表示不支持。

使用指南

从v0版本升级

所有Storage S3插件API现在返回一个操作对象而不是结果对象。该操作对象提供了对飞行中请求的更多控制,例如取消、暂停和恢复能力(视API而定)。结果 Future 可以通过 .result 属性获取。

示例代码

上传文件
// before
final result = await Amplify.Storage.uploadFile(
    local: exampleFile,
    key: 'ExampleKey',
);
print('Uploaded file key: ${result.key}')

// after
final result = await Amplify.Storage.uploadFile(
    localFile: exampleFile,
    key: 'ExampleKey',
).result;
print('Uploaded file key: ${result.uploadedItem.key}');
下载文件
// before
final result = await Amplify.Storage.downloadFile(
  key: 'ExampleKey',
  local: file,
);
print('Downloaded local file path: ${result.file.path}')


// after
final result = await Amplify.Storage.downloadFile(
  key: 'ExampleKey',
  localFile: file,
).result;
print('Downloaded file key: ${result.downloadedItem.key}');
print('Downloaded local file path: ${result.localFile.path}');
列出文件
// before
final result = await Amplify.Storage.list();
print('Listed items: ${result.items}');

// after
final result = await Amplify.Storage.list().result;
print('Listed items: ${result.items}');
print('Are there more items can be listed? ${result.hasNextPage}');
print('List nextToken: ${result.nextToken}');
删除文件
// before
final result = await Amplify.Storage.remove(
  key: key,
);
print('Removed file key: ${result.key}');

// after
final result = await Amplify.Storage.remove(
  key: key,
).result;
print('Removed file key: ${result.removedItem.key}');
获取URL
// before
final result = await Amplify.Storage.getUrl(key: 'ExampleKey');
print('Got url: ${result.url}');

// after
final result = await Amplify.Storage.getUrl(key: 'ExampleKey').result;
print('Got url: ${result.url.toString()}');

完整示例Demo

以下是一个完整的Flutter应用程序示例,展示了如何配置和使用amplify_storage_s3插件。

main.dart

import 'package:amplify_auth_cognito/amplify_auth_cognito.dart';
import 'package:amplify_authenticator/amplify_authenticator.dart';
import 'package:amplify_core/amplify_core.dart';
import 'package:amplify_secure_storage/amplify_secure_storage.dart';
import 'package:amplify_storage_s3/amplify_storage_s3.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:path_provider/path_provider.dart';

import 'amplify_outputs.dart';

final AmplifyLogger _logger = AmplifyLogger('MyStorageApp');

void main() {
  AmplifyLogger().logLevel = LogLevel.debug;
  runApp(
    const MyApp(
      title: 'Amplify Storage Example',
    ),
  );
}

class MyApp extends StatefulWidget {
  const MyApp({super.key, required this.title});

  final String title;

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  static final _router = GoRouter(
    routes: [
      GoRoute(
        path: '/',
        builder: (BuildContext _, GoRouterState __) => const HomeScreen(),
      ),
    ],
  );

  Future<void> configureAmplify() async {
    final auth = AmplifyAuthCognito(
      secureStorageFactory: AmplifySecureStorage.factoryFrom(
        macOSOptions: MacOSSecureStorageOptions(useDataProtection: false),
      ),
    );
    final storage = AmplifyStorageS3();

    try {
      await Amplify.addPlugins([auth, storage]);
      await Amplify.configure(amplifyConfig);
      _logger.debug('Successfully configured Amplify');
    } on Exception catch (error) {
      _logger.error('Something went wrong configuring Amplify: $error');
    }
  }

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

  @override
  Widget build(BuildContext context) {
    return Authenticator(
      preferPrivateSession: true,
      child: MaterialApp.router(
        title: 'Flutter Demo',
        builder: Authenticator.builder(),
        theme: ThemeData.light(useMaterial3: true),
        darkTheme: ThemeData.dark(useMaterial3: true),
        routeInformationParser: _router.routeInformationParser,
        routerDelegate: _router.routerDelegate,
        debugShowCheckedModeBanner: false,
      ),
    );
  }
}

class HomeScreen extends StatefulWidget {
  const HomeScreen({super.key});

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  List<StorageItem> list = [];
  var imageUrl = '';

  Future<void> _signOut() async {
    try {
      await Amplify.Auth.signOut();
      _logger.debug('Signed out');
    } on AuthException catch (e) {
      _logger.error('Could not sign out - ${e.message}');
    }
  }

  Future<void> _checkAuthStatus() async {
    try {
      final session = await Amplify.Auth.fetchAuthSession();
      _logger.debug('Signed in: ${session.isSignedIn}');
    } on AuthException catch (e) {
      _logger.error('Could not check auth status - ${e.message}');
    }
  }

  Future<void> _uploadFile() async {
    final result = await FilePicker.platform.pickFiles(
      type: FileType.image,
      withReadStream: true,
      withData: false,
    );

    if (result == null) {
      _logger.debug('No file selected');
      return;
    }

    final platformFile = result.files.single;

    try {
      await Amplify.Storage.uploadFile(
        localFile: AWSFile.fromStream(
          platformFile.readStream!,
          size: platformFile.size,
        ),
        path: StoragePath.fromString('public/${platformFile.name}'),
        onProgress: (p) =>
            _logger.debug('Uploading: ${p.transferredBytes}/${p.totalBytes}'),
      ).result;
      await _listAllPublicFiles();
    } on StorageException catch (e) {
      _logger.error('Error uploading file - ${e.message}');
    }
  }

  Future<void> _listAllPublicFiles() async {
    try {
      final result = await Amplify.Storage.list(
        path: const StoragePath.fromString('public/'),
        options: const StorageListOptions(
          pluginOptions: S3ListPluginOptions.listAll(),
        ),
      ).result;
      setState(() {
        list = result.items;
      });
    } on StorageException catch (e) {
      _logger.error('List error - ${e.message}');
    }
  }

  Future<void> downloadFileMobile(String path) async {
    final documentsDir = await getApplicationDocumentsDirectory();
    final filepath = '${documentsDir.path}/$path';
    try {
      await Amplify.Storage.downloadFile(
        path: StoragePath.fromString(path),
        localFile: AWSFile.fromPath(filepath),
        onProgress: (p0) =>
            _logger.debug('Progress: ${(p0.transferredBytes / p0.totalBytes) * 100}%'),
      ).result;
      await _listAllPublicFiles();
    } on StorageException catch (e) {
      _logger.error('Download error - ${e.message}');
    }
  }

  Future<void> downloadFileWeb(String path) async {
    try {
      await Amplify.Storage.downloadFile(
        path: StoragePath.fromString(path),
        localFile: AWSFile.fromPath(path),
        onProgress: (p0) =>
            _logger.debug('Progress: ${(p0.transferredBytes / p0.totalBytes) * 100}%'),
      ).result;
      await _listAllPublicFiles();
    } on StorageException catch (e) {
      _logger.error('Download error - ${e.message}');
    }
  }

  Future<void> removeFile(String path) async {
    try {
      await Amplify.Storage.remove(
        path: StoragePath.fromString(path),
      ).result;
      setState(() {
        imageUrl = '';
      });
      await _listAllPublicFiles();
    } on StorageException catch (e) {
      _logger.error('Delete error - ${e.message}');
    }
  }

  Future<String> getUrl(String path) async {
    try {
      final result = await Amplify.Storage.getUrl(
        path: StoragePath.fromString(path),
        options: const StorageGetUrlOptions(
          pluginOptions: S3GetUrlPluginOptions(
            validateObjectExistence: true,
            expiresIn: Duration(minutes: 1),
          ),
        ),
      ).result;
      setState(() {
        imageUrl = result.url.toString();
      });
      return result.url.toString();
    } on StorageException catch (e) {
      _logger.error('Get URL error - ${e.message}');
      rethrow;
    }
  }

  @override
  void initState() {
    super.initState();
    _checkAuthStatus();
    _listAllPublicFiles();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Amplify Storage Example'),
      ),
      body: Stack(
        children: [
          Center(
            child: Padding(
              padding: const EdgeInsets.all(20),
              child: ListView.builder(
                itemCount: list.length,
                itemBuilder: (BuildContext context, int index) {
                  final item = list[index];
                  return ListTile(
                    onTap: () {
                      getUrl(item.path);
                    },
                    title: Text(item.path),
                    trailing: IconButton(
                      icon: const Icon(Icons.delete),
                      onPressed: () {
                        removeFile(item.path);
                      },
                      color: Colors.red,
                    ),
                    leading: IconButton(
                      icon: const Icon(Icons.download),
                      onPressed: () {
                        zIsWeb
                            ? downloadFileWeb(item.path)
                            : downloadFileMobile(item.path);
                      },
                    ),
                  );
                },
              ),
            ),
          ),
          if (imageUrl != '')
            Align(
              alignment: Alignment.bottomCenter,
              child: Padding(
                padding: const EdgeInsets.all(80),
                child: Image.network(imageUrl, height: 200),
              ),
            ),
          Align(
            alignment: Alignment.bottomCenter,
            child: Padding(
              padding: const EdgeInsets.all(20),
              child: ElevatedButton(
                onPressed: _uploadFile,
                child: const Text('Upload File'),
              ),
            ),
          ),
          Align(
            alignment: Alignment.bottomLeft,
            child: Padding(
              padding: const EdgeInsets.all(20),
              child: ElevatedButton(
                style: ButtonStyle(
                  backgroundColor: MaterialStateProperty.all(Colors.red),
                ),
                onPressed: _signOut,
                child: const Icon(Icons.logout, color: Colors.white),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

迁移指南

更多信息请参考迁移指南

以上是关于amplify_storage_s3插件的详细使用说明及示例代码,希望对你有所帮助!


更多关于Flutter AWS S3存储管理插件amplify_storage_s3的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter AWS S3存储管理插件amplify_storage_s3的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter应用中使用amplify_storage_s3插件来管理AWS S3存储的示例代码。这个示例将展示如何配置AWS Amplify,上传和下载文件到S3存储。

前提条件

  1. AWS Amplify 配置:确保你已经在AWS Amplify控制台中设置了你的项目,并配置了S3存储桶。
  2. Flutter 环境:Flutter SDK 已安装,并配置好开发环境。

步骤

  1. 添加依赖

    在你的pubspec.yaml文件中添加amplify_flutteramplify_storage_s3依赖:

    dependencies:
      flutter:
        sdk: flutter
      amplify_flutter: ^0.x.x  # 请检查最新版本号
      amplify_storage_s3: ^0.x.x  # 请检查最新版本号
    

    然后运行flutter pub get来安装依赖。

  2. 配置Amplify

    在你的Flutter项目中,创建一个amplifyconfiguration.json文件,并根据AWS Amplify控制台中生成的配置内容填写。例如:

    {
      "awsconfig": {
        "Region": "us-west-2",
        "UserPoolId": "us-west-2_xxxxxxx",
        "UserPoolWebClientId": "xxxxxxx",
        "IdentityPoolId": "us-west-2:xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx",
        "AuthenticationType": "USER_POOL_AND_CLIENT_CREDENTIALS"
      },
      "api": {
        "endpoints": {}
      },
      "storage": {
        "plugins": {
          "awsS3StoragePlugin": {
            "bucket": "your-bucket-name",
            "region": "us-west-2",
            "defaultAccessLevel": "guest"
          }
        }
      }
    }
    
  3. 初始化Amplify

    在你的main.dart文件中初始化Amplify:

    import 'package:flutter/material.dart';
    import 'package:amplify_flutter/amplify.dart';
    import 'package:amplify_storage_s3/amplify_storage_s3.dart';
    import 'amplifyconfiguration.json' as config;
    
    void main() async {
      // 加载配置
      Amplify.configure(config: config.defaultConfig);
    
      // 检查配置是否成功
      try {
        await Amplify.addPlugin(new AWSS3StoragePlugin());
        await Amplify.configure();
        print("Amplify configured successfully");
      } catch (e) {
        print("Failed to configure Amplify: $e");
      }
    
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(),
        );
      }
    }
    
  4. 上传和下载文件

    在你的MyHomePage或其他组件中实现文件上传和下载功能:

    import 'package:flutter/material.dart';
    import 'package:amplify_storage_s3/amplify_storage_s3.dart';
    import 'dart:typed_data/uint8list.dart';
    
    class MyHomePage extends StatefulWidget {
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      String uploadStatus = "";
      String downloadStatus = "";
    
      void uploadFile() async {
        // 示例文件数据
        Uint8List fileData = Uint8List.fromList("Hello, this is a test file.".codeUnits);
        String keyName = "test/test.txt";
    
        try {
          await Storage.uploadFile(key: keyName, data: fileData);
          setState(() {
            uploadStatus = "File uploaded successfully!";
          });
        } catch (e) {
          setState(() {
            uploadStatus = "Failed to upload file: $e";
          });
        }
      }
    
      void downloadFile() async {
        String keyName = "test/test.txt";
    
        try {
          AmplifyStorageDownloadResult result = await Storage.downloadFile(key: keyName);
          Uint8List fileData = result.data;
          String fileContent = String.fromCharCodes(fileData);
          setState(() {
            downloadStatus = "File content: $fileContent";
          });
        } catch (e) {
          setState(() {
            downloadStatus = "Failed to download file: $e";
          });
        }
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text("AWS S3 Storage Management"),
          ),
          body: Padding(
            padding: const EdgeInsets.all(16.0),
            child: Column(
              children: <Widget>[
                Text("Upload Status: $uploadStatus"),
                ElevatedButton(
                  onPressed: uploadFile,
                  child: Text("Upload File"),
                ),
                Text("Download Status: $downloadStatus"),
                ElevatedButton(
                  onPressed: downloadFile,
                  child: Text("Download File"),
                ),
              ],
            ),
          ),
        );
      }
    }
    

注意事项

  • 确保你的AWS Amplify配置正确,包括用户池、身份池和S3存储桶的配置。
  • 根据你的需求调整上传和下载逻辑,比如处理大文件或复杂的数据结构。
  • 处理异常和错误情况,确保用户有适当的反馈。

这个示例展示了如何在Flutter应用中使用amplify_storage_s3插件来管理AWS S3存储。根据你的具体需求,你可能需要调整代码以符合你的应用场景。

回到顶部