Khám phá công nghệ

Khám phá các công cụ và kỹ thuật hữu ich cho Lập trình viên

Hướng dẫn Upload Hình Ảnh Lên Supabase Storage Trong Flutter

Thắng Nguyễn

Fri, 17 Jan 2025

Hướng dẫn Upload Hình Ảnh Lên Supabase Storage Trong Flutter

Supabase là một nền tảng backend tuyệt vời dành cho lập trình viên, cung cấp các tính năng như xác thực, quản lý cơ sở dữ liệu và lưu trữ xử lý file media. Bài viết này hướng dẫn bạn cách upload hình ảnh lên Supabase storage bằng Flutter.

Yêu cầu

Đảm bảo bạn đã có:

  1. Dự án Flutter đã được cấu hình.
  2. Cài đặt Supabase trong dự án của bạn. (Tham khảo Supabase Flutter Setup nếu bạn chưa quen với Supabase.)
  3. Tạo một bucket trong Supabase storage (ví dụ: images).

Bước 1: Thêm Dependencies Cần Thiết

Thêm các gói cần thiết vào tệp pubspec.yaml:

dependencies: flutter: sdk: flutter image_picker: ^0.8.7+5 permission_handler: ^10.4.3 supabase_flutter: ^1.3.1

Chạy lệnh sau để cài đặt các dependencies:

flutter pub get

Bước 2: Cấu Hình Supabase

Khởi tạo Supabase trong tệp main.dart:

import 'package:flutter/material.dart'; import 'package:supabase_flutter/supabase_flutter.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); await Supabase.initialize( url: 'YOUR_SUPABASE_URL', anonKey: 'YOUR_SUPABASE_ANON_KEY', ); runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, home: ProfilePage(), ); } }

Thay YOUR_SUPABASE_URLYOUR_SUPABASE_ANON_KEY bằng thông tin dự án Supabase của bạn.


Bước 3: Xây Dựng Giao Diện Upload Ảnh

Code Cho Profile Page

Dưới đây là đoạn mã cho widget ProfilePage, xử lý việc chọn, hiển thị và upload hình ảnh:

import 'dart:io'; import 'package:flutter/material.dart'; import 'package:image_picker/image_picker.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:supabase_flutter/supabase_flutter.dart'; class ProfilePage extends StatefulWidget { const ProfilePage({super.key}); @override State<ProfilePage> createState() => _ProfilePageState(); } class _ProfilePageState extends State<ProfilePage> { File? _imageFile; bool _isUploading = false; Future<void> pickImage() async { try { if (Platform.isAndroid) { await requestPermission(); } final picker = ImagePicker(); final XFile? image = await picker.pickImage(source: ImageSource.gallery); if (image != null) { setState(() { _imageFile = File(image.path); }); } } catch (e) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Lỗi khi chọn ảnh: $e')), ); } } Future<void> uploadImage() async { if (_imageFile == null) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Vui lòng chọn ảnh trước.')), ); return; } setState(() { _isUploading = true; }); try { final fileName = DateTime.now().millisecondsSinceEpoch.toString(); final path = 'uploads/$fileName'; await Supabase.instance.client.storage .from('images') .upload(path, _imageFile!); ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Upload thành công! File: $path')), ); } catch (e) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Lỗi upload ảnh: ${e.toString()}')), ); } finally { setState(() { _isUploading = false; }); } } Future<void> requestPermission() async { if (Platform.isAndroid) { if (await Permission.photos.isDenied || await Permission.photos.isPermanentlyDenied) { await Permission.photos.request(); } } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text("Profile")), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ CircleAvatar( radius: 50, backgroundImage: _imageFile != null ? FileImage(_imageFile!) : null, child: _imageFile == null ? const Icon(Icons.person, size: 50) : null, ), const SizedBox(height: 20), ElevatedButton( onPressed: pickImage, child: const Text('Chọn Ảnh'), ), ElevatedButton( onPressed: _isUploading ? null : uploadImage, child: _isUploading ? const CircularProgressIndicator() : const Text('Cập Nhật Ảnh'), ), ], ), ), ); } }

Bước 4: Cấp Quyền Truy Cập

Android

Thêm quyền vào tệp AndroidManifest.xml:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />

iOS

Thêm các khóa sau vào Info.plist:

<key>NSPhotoLibraryUsageDescription</key> <string>Chúng tôi cần quyền truy cập thư viện ảnh để chọn hình.</string>

Kết Luận

Trong bài viết này, chúng ta đã tạo ứng dụng Flutter cho phép người dùng chọn ảnh, upload lên Supabase storage và hiển thị trong CircleAvatar. Supabase giúp xử lý file media dễ dàng, kết hợp với Flutter để xây dựng ứng dụng linh hoạt và tương tác cao.

0 Comments

Để lại một bình luận