1. 程式人生 > 其它 >Flutter從相簿選擇圖片並顯示出來,上傳到伺服器

Flutter從相簿選擇圖片並顯示出來,上傳到伺服器

技術標籤:FlutterAndroid

文章目錄


在Android中從手機相簿選擇一些圖片出來是很常用的功能。Flutter也提供了很好用的第三方庫可以幫助我們快速實現這個需求。

實現效果如下

在這裡插入圖片描述在這裡插入圖片描述在這裡插入圖片描述在這裡插入圖片描述

接下來看看該怎麼用。

匯入依賴包

版本號可以到puv.dev上查詢最新的替換上去。

dependencies:
  multi_image_picker: ^4.6.1

multi_image_picker的使用

使用這個外掛也很簡單。首先匯入包

import 'package:multi_image_picker/multi_image_picker.dart';

接著就訪問相簿選擇圖片。

  • 先定義一個List<Asset> resultList用於儲存選擇後的圖片資訊。
  • MultiImagePicker.pickImages的返回型別是List<Asset>
  • 相關引數使用看程式碼中的註釋
  // 選擇照片並上傳
  Future<void> uploadImages() async {
    if (resultList == null) {
      resultList = List<Asset>();
    }
    try {
      var tmp = await MultiImagePicker.pickImages(
        // 可選引數, 若resultList不為空,再次開啟選擇介面的適合,可以顯示之前選中的圖片資訊。 
        selectedAssets: resultList,
        // 選擇圖片的最大數量
        maxImages: 9,
        // 是否支援拍照
        enableCamera: true,
        materialOptions: MaterialOptions(
          // 顯示所有照片,值為 false 時顯示相簿
            startInAllView: false,
            allViewTitle: '所有照片',
            actionBarColor: '#2196F3',
            textOnNothingSelected: '沒有選擇照片'),
      );
      if (tmp.length != 0) {
        resultList = tmp;
        setState(() {});
      }
    } on Exception catch (e) {
      e.toString();
    }
  }

這樣選擇圖片的功能就以及做好了。

顯示圖片

接下來實現顯示圖片的功能。

使用gridview顯示。

因為選擇後的圖片是一個Asset型別。所以可以使用 AssetThumb顯示圖片

AssetThumb(
    asset: resultList[index],
    width: 300,
    height: 300,
)
 @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
    title: Text('發動態'),
    actions: [
      IconButton(
          icon: Icon(Icons.send),
          onPressed: () async {


          })
    ],
      ),
      body: Container(
    padding: EdgeInsets.all(5),
    child: ListView(
      children: [
        TextField(
          controller: _controller,
          decoration: InputDecoration(
              border: OutlineInputBorder(), hintText: '說點什麼……'),
          maxLines: 7,
        ),
        Row(
          children: [
            RaisedButton(
              onPressed: () {
                uploadImages();
              },
              child: Text('選擇圖片'),
            ),
          ],
        ),
        Container(
          width: double.infinity,
          height: 1000,
          child: GridView.builder(
            padding: EdgeInsets.all(0),
            gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 3,
                crossAxisSpacing: 2,
                mainAxisSpacing: 2),
            itemBuilder: (BuildContext context, int index) {
              return _createGridViewItem(
                  AssetThumb(
                    asset: resultList[index],
                    width: 300,
                    height: 300,
                  ),
                  index);
            },
            itemCount: resultList.length,
          ),
        )
      ],
    ),
      ),
    );
  } 

_createGridViewItem(widget, index) {
    return Container(
      height: 100,
      width: 100,
      padding: EdgeInsets.all(0),
      margin: EdgeInsets.all(0),
      child: Stack(
        children: [
          widget,
          Positioned(
            top: 0,
            right: 0,
            child: GestureDetector(
              onTap: () {
                setState(() {
                  resultList.removeAt(index);
                });
              },
              child: Icon(
                Icons.close,
                color: Colors.grey,
              ),
            ),
          )
        ],
      ),
    );
  }

上傳圖片

匯入依賴dio

dependencies:  
  dio: ^3.0.10
  dio_log: ^1.3.5

dio中提供了檔案上傳的方式,具體可以去看官方文件。

  • MultipartFile 是Dio中使用者檔案上傳的類
  • 如果一次性需要傳多個圖片,可以用一個List陣列儲存
          List<MultipartFile> files = List();
					//  resultList就是之前獲取選擇圖片的List
              for (int i = 0; i < resultList.length; i++) {
                // 獲取 ByteData
                ByteData byteData = await resultList[i].getByteData();
                List<int> imageData = byteData.buffer.asUint8List();

                MultipartFile multipartFile = MultipartFile.fromBytes(
                  imageData,
                  // 檔名
                  filename: 'some-file-name.jpg',
                  // 檔案型別
                  contentType: MediaType("image", "jpg"),
                );

                files.add(multipartFile);
              }

封裝到FormData裡面。

  • 這裡的image就是後端介面中接收檔案的引數名。如果傳入的是一個數組,則會自動加上[]
              FormData formData = FormData.fromMap({
                // 後端介面的引數名稱
                "image": files,
              });

之後就可以上傳了。

              HttpUtils.instance.post("/upload", formData,
                  success: (response) {
                      //這部分是對相應結果的處理,大家可以根據自己返回的資料型別進行修改
                    if (response['code'] == 200) {
                      List list = response['data'];

                      for (var i = 0; i < list.length; i++) {
                        if (i != 0) urls += "¥";
                        urls += list[i];
                      }
                    }

                  });

可能遇到的問題

理論上使用multi_image_picker是不用管許可權問題的,但是如果遇到了Permission denied的情況的話,則開啟
android\app\src\main\AndroidManifest.xml這個檔案
然後加上這幾個許可權

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="cn.jxj4869.flutter_imagepick_demo">

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

完整程式碼已經上傳GitHubhttps://github.com/jiang4869/CSDNBlogCode/tree/master/flutter_imagepick_demo,喜歡的話可以start一些。這個demo是動態上傳介面。可以傳送文字和圖片資訊。

拒絕白嫖,從點一鍵三連開始