iT邦幫忙

2022 iThome 鐵人賽

DAY 10
0
Mobile Development

在 Flutter 開發旅程的手札系列 第 10

Flutter Package - 將手機照片上傳到API上

  • 分享至 

  • xImage
  •  

今天我會介紹該如何用image_picker套件,讓手機照片能上傳到APP內

輸入下方指令下載套件

flutter pub add image_picker

到ios>Runner>info.plist,設定照片相關的取得使用者權限設定

  1. 設定「相簿」:NSPhotoLibraryUsageDescription
  2. 設定「相機」:NSCameraUsageDescription
  3. 設定「麥克風」(依需求斟酌增加):NSMicrophoneUsageDescription
    <key>NSPhotoLibraryUsageDescription</key>
    <string>This app requires permission to access photo library</string>
    <key>NSCameraUsageDescription</key>
    <string>This app requires permission to access camera</string>
    <key>NSMicrophoneUsageDescription</key>
    <string>This app requires permission to access microphone</string>

https://ithelp.ithome.com.tw/upload/images/20220925/20152683IpSFaNWdMz.png


新增一個upload_image_widget.dart檔案,來製作拍攝相機或選擇照片的彈跳視窗

import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';

class UploadImageWidget extends StatelessWidget {
  final void Function(String) onImagePicked;
  final Widget child;

  const UploadImageWidget({Key? key, required this.child, required this.onImagePicked}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        _showOptions(context);
      },
      child: child,
    );
  }

  void _showOptions(BuildContext context) {
    showModalBottomSheet(
        context: context,
        builder: (context) {
          return SizedBox(
              height: 150,
              child: Column(children: <Widget>[
                ListTile(
                    onTap: () async {
                      Navigator.pop(context);
                      var path = await _showCameraLibrary();
                      onImagePicked(path);
                    },
                    leading: const Icon(Icons.photo_camera),
                    title: const Text("拍攝照片")),
                ListTile(
                    onTap: () async {
                      Navigator.pop(context);
                      var path = await _showPhotoLibrary();
                      onImagePicked(path);
                    },
                    leading: const Icon(Icons.photo_library),
                    title: const Text("選擇照片"))
              ]));
        });
  }

  Future<String> _showCameraLibrary() async {
    ImagePicker picker = ImagePicker();
    XFile? image = await picker.pickImage(source: ImageSource.camera);

    return image!.path;
  }

  Future<String> _showPhotoLibrary() async {
    ImagePicker picker = ImagePicker();
    XFile? image = await picker.pickImage(source: ImageSource.gallery);

    return image!.path;
  }
}

在使用的StatefulWidget輸入下方語法

  String _path = "";
UploadImageWidget(
              onImagePicked: (path) {
                setState(() {
                  _path = path;
                });
              },
              child: _path == ""
                  ? Container(
                      height: 100,
                      width: 100,
                      decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(13),
                        color: const Color(0xFFCCCCCC),
                      ),
                      child: Icon(Icons.collections_outlined),
                    )
                  : SizedBox(
                      height: 100,
                      width: 100,
                      child: ClipRRect(
                        borderRadius: BorderRadius.circular(13),
                        child: Image.file(
                          File(_path),
                          fit: BoxFit.cover,
                        ),
                      ),
                    ),
            ),

Demo 將手機照片上傳到app內


若還沒有學會製作api的朋友可以參考下方三篇文章
Flutter Package — 串接api(一)
Flutter Package — 串接api(二)
Flutter Package — 串接api(三)

新增add_photo_response.dart檔案,來接收api回傳的資料

import 'package:json_annotation/json_annotation.dart';

part 'add_photo_response.g.dart';

@JsonSerializable()
class AddPhotoResponse {
  bool success;
  AddPhotoResponse({
    required this.success,
  });
  factory AddPhotoResponse.fromJson(Map<String, dynamic> json) => _$AddPhotoResponseFromJson(json);
}

在api.dart檔案下輸入

@POST("photo")
@MultiPart()
Future<AddPhotoResponse> addPhoto(@Part() File photo);

在app_repository.dart檔案下輸入

Future<AddPhotoResponse> addPhoto(File photo) async {
    return await _client.addPhoto(photo); 
}

在剛才的StatefulWidget新增一個按鈕,點擊後上傳照片至api

    ElevatedButton(
              onPressed: () async {
                if (_path != "") {
                  final photoInfo = await RepositoryProvider.of<AppRepository>(context).addPhoto(File(_path));
                  ScaffoldMessenger.of(context).showSnackBar(SnackBar(
                    content: Text(photoInfo.success),
                  ));
                }
              },
              child: const Text("Post Button"),
            )

api上傳照片範例(因沒找到可以上傳的免費api因此無法提供實作成果)


上一篇
Flutter Package - 更換APP的ICON
下一篇
Flutter Widget - 製作搜尋列表
系列文
在 Flutter 開發旅程的手札30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言