Flutter上传文件到服务器

tech2025-05-20  13

好久没写了,一直没时间,项目太紧,而且自己也变懒了许多。现在就发一下自己简简单单的封装类吧,一个上传服务器的一个封装。因为很多人问我在选择之后在选择无法去保存上次选择的文件。其实我也没多说什么。就说了一个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<dynamic> list) callback; //上传服务器接口的回调 final Function(List<dynamic> 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<WrapMultiImagePicker> { List<Asset> images = List<Asset>(); List<dynamic> imagesUrlData = []; bool error = false; GlobalKey _key = new GlobalKey(); Future<void> loadAssets() async { List<Asset> resultList = List<Asset>(); 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<Asset> 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<String> _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<Widget> _showImageWrap(){ List<Widget> tempList = []; for (int i = 0; i < images.length; i++) { Asset asset = images[i]; tempList.add(Container( width: 100, height: 100, child: Stack( children: <Widget>[ 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: <Widget>[ 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<Map<String,dynamic>> upMultiFileLoadClient({@required List<String> imagesUrlList}) async { List<MultipartFile> _files = []; for(var i =0;i < imagesUrlList.length;i++){ final MultipartFile _file = MultipartFile.fromFileSync(imagesUrlList[i]); if(_file != null){ _files.add(_file); } } Map<String,dynamic> 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; } }

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

最新回复(0)