Flutter上传文件到服务器

好久没写了,一直没时间,项目太紧,而且自己也变懒了许多。现在就发一下自己简简单单的封装类吧,一个上传服务器的一个封装。因为很多人问我在选择之后在选择无法去保存上次选择的文件。其实我也没多说什么。就说了一个set去重。在这里我就把我最简单的一个封装拿来用。这里我用的是一个multi_image_picker这个插件。我也不多说什么了直接上代码了。只要copy下来修改一下自己的网络配置就能使用。

import 'dart:io';

import 'package:---------/pages/login_pages/bloc/uoload_image/upload_repository.dart';
import 'package:---------/utils/file_util.dart';
import 'package:---------/utils/toast_util.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:multi_image_picker/multi_image_picker.dart';

/*
* 重新封装图片多选
* 使用直接可以看定义的参数
* */
class WrapMultiImagePicker extends StatefulWidget {
  final int maxChoose; //图片最大的选择个数
  final Function(List list) callback; //上传服务器接口的回调
  final Function(List list) deleteCallback; //删除照片后的回调

  const WrapMultiImagePicker(
      {Key key,
         this.maxChoose = 9,
        @required this.callback,
        @required this.deleteCallback,
      })
      : super(key: key);

  @override
  _WrapMultiImagePickerState createState() => _WrapMultiImagePickerState();
}

class _WrapMultiImagePickerState extends State {
  List images = List();
  List imagesUrlData = [];
  bool error = false;
  GlobalKey _key = new GlobalKey();

  Future loadAssets() async {
    List resultList = List();

    try {
      resultList = await MultiImagePicker.pickImages(
        maxImages: widget.maxChoose,
        enableCamera: true,
        selectedAssets: images,
        cupertinoOptions: CupertinoOptions(takePhotoIcon: "chat"),
        materialOptions: MaterialOptions(
          actionBarColor: "#abcdef",
          actionBarTitle: "选择图片",
          allViewTitle: "All Photos",
          useDetailsView: false,
          selectCircleStrokeColor: "#000000",
        ),
      );
    } on Exception catch (e) {
      if (mounted) {
        setState(() {
          error = true;
        });
      }
    }
    if (!mounted) return;

    setState(() {
      Set showImages = new Set();
      for (var item in resultList) {
        showImages.add(item);
      }
      images = [];
      for (var item in showImages) {
        images.add(item);
      }

      _uploadClient();
    });
  }

  // 上传服务器
  void _uploadClient() async {
    List _imagesUrlList = [];
    for (int i = 0; i < images.length; i++) {
      ByteData byteData =
          await images[i].getByteData(quality: 10); //quality这是一个压缩的比例
      String prePath =
          await FileUtil.getInstance().getSavePath("/updateImage/");
      String name = DateTime.now().millisecondsSinceEpoch.toString() + ".png";
      File _imageFile = await File(prePath + name)
          .writeAsBytes(byteData.buffer.asUint8List());
      if (_imageFile != null) {
        _imagesUrlList.add(_imageFile.path);
      }
    }
    final res = await UploadRepository.upMultiFileLoadClient(
        imagesUrlList: _imagesUrlList);

    if (res["code"] == 0) {
      if (widget.callback != null) {
        imagesUrlData = res["data"];
        widget.callback(imagesUrlData);
      }
    } else {
      T.show(msg: "上传服务器失败,请重新操作");
    }
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.symmetric(horizontal: 15.w),
      child: Container(
        width: double.infinity,
        child: Wrap(
          spacing: 10.w,
          runSpacing: 10.h,
          children: _showImageWrap(),
        ),
      ),
    );
  }

  List _showImageWrap(){
    List tempList = [];
    for (int i = 0; i < images.length; i++) {
      Asset asset = images[i];
      tempList.add(Container(
        width: 100,
        height: 100,
        child: Stack(
          children: [
            ClipRRect(
              borderRadius: BorderRadius.circular(5),
              child: AssetThumb(
                asset: asset,
                width: 100,
                height: 100, //这里的宽高似乎不影响显示的大小
              ),
            ),
            Positioned(
              right: 3,
              top: 3,
              child: InkWell(
                  onTap: (){
                    print("index::::$i");
                    images.removeAt(i);
                    imagesUrlData.removeAt(i);
                    if(widget.deleteCallback != null){
                      widget.deleteCallback(imagesUrlData);
                    }
                    if(mounted){
                      setState(() {

                      });
                    }
                  },
                  child: Icon(Icons.cancel,size: 20.ssp,)),
            ),
          ],
        ),
      ));
    }

    if (images.length < widget.maxChoose) {
      tempList.add(InkWell(
        onTap: loadAssets,
        child: Container(
          key: _key,
          width: 100,
          height: 100,
          decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(5),
            color: Color(0xffa0a8ac),
          ),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Icon(
                Icons.add,
                size: 32,
                color: Colors.white,
              ),
              SizedBox(
                height: 5.h,
              ),
              Text(
                "请上传图片",
                style: TextStyle(fontSize: 11.ssp, color: Color(0xff333333)),
              ),
            ],
          ),
        ),
      ));
    }

    return tempList;
  }
}



import 'dart:io';

import 'package:----------/network_manage/http_utils/http.dart';
import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';

class UploadRepository{
  static const _aliyunClientUrl = "你的服务器的地址";

  static Future> upMultiFileLoadClient({@required List imagesUrlList}) async {
    List _files = [];
    for(var i =0;i < imagesUrlList.length;i++){
      final MultipartFile _file = MultipartFile.fromFileSync(imagesUrlList[i]);
      if(_file != null){
        _files.add(_file);
      }
    }
    Map response = await HttpUtil().postUpload(
        _aliyunClientUrl,
        formData: FormData.fromMap({
          "files": _files
        }),
        options: Options(
          receiveTimeout: 200000,
            sendTimeout: 200000,
            headers: {  //上传服务器的头信息
          "Content-Type": "multipart/form-data",
        }
        ),
        progressCallback: (int count, int total){
          print("进度::::${(count * 100 / total).toStringAsFixed(2)}%");
        }
    );
    print("上传阿里云::::$response");
    if(response["code"] != 0){
      throw Exception(response["msg"] ?? "上传服务器失败");
    }

    return response;
  }
}

由于我这里是先显示的本地然后去用服务器的数据同步自己的操作,这里需要你们自己的服务器是好的。如果上传失败是出现选择后消失的问题,这是因为服务器没上传上去的原因。只要保证接口没问题,这个可以直接拿下来就能用

你可能感兴趣的:(Flutter实战,Flutter/Dart,Flutter/Dart基础,flutter,dart)