Flutter从相册选择图片并显示出来,上传到服务器

Posted jiangxiaoju

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter从相册选择图片并显示出来,上传到服务器相关的知识,希望对你有一定的参考价值。

文章目录


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是动态上传界面。可以发送文字和图片信息。

拒绝白嫖,从点一键三连开始

以上是关于Flutter从相册选择图片并显示出来,上传到服务器的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 调用原生硬件 Api 实现照相机 拍照和相册选择 以及拍照上传

Android中拍照(相册中选择)并上传图片功能(包括动态获取权限)

flutter图片保存到手机相册

如何区分捕获图像相册选择的图像

H5调用手机相机和相册,并且将图片转化为base64的格式

swift -从相册中选择照片并上传