Flutter单图片上传转多图片上传实现方案咨询
Flutter 单图上传改造为多图上传方案
以下是改造后的完整代码,支持一次性选择多张图片并批量上传:
import 'dart:convert'; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:image_picker/image_picker.dart'; import 'package:http/http.dart' as http; class UploadImageDemo extends StatefulWidget { UploadImageDemo() : super(); final String title = "Upload Image Demo"; @override UploadImageDemoState createState() => UploadImageDemoState(); } class UploadImageDemoState extends State<UploadImageDemo> { static final String uploadEndPoint = 'http://localhost/flutter_test/upload_image.php'; Future<List<File>> files; String status = ''; List<String> base64Images = []; List<File> tmpFiles = []; String errMessage = 'Error Uploading Images'; int uploadedCount = 0; chooseImages() { setState(() { files = ImagePicker.pickMultiImage(source: ImageSource.gallery); }); setStatus(''); uploadedCount = 0; base64Images.clear(); tmpFiles.clear(); } setStatus(String message) { setState(() { status = message; }); } startUpload() { if (tmpFiles.isEmpty) { setStatus(errMessage); return; } setStatus('Uploading ${tmpFiles.length} images...'); uploadedCount = 0; // 循环上传每张图片 for (int i = 0; i < tmpFiles.length; i++) { String fileName = tmpFiles[i].path.split('/').last; upload(fileName, i); } } upload(String fileName, int index) { http.post(uploadEndPoint, body: { "image": base64Images[index], "name": fileName, }).then((result) { setState(() { uploadedCount++; }); if (uploadedCount == tmpFiles.length) { setStatus(result.statusCode == 200 ? 'All ${tmpFiles.length} images uploaded successfully!' : errMessage); } else { setStatus('Uploaded $uploadedCount/${tmpFiles.length} images'); } }).catchError((error) { setStatus('Upload failed at $uploadedCount/${tmpFiles.length}: $error'); }); } Widget showImages() { return FutureBuilder<List<File>>( future: files, builder: (BuildContext context, AsyncSnapshot<List<File>> snapshot) { if (snapshot.connectionState == ConnectionState.done && null != snapshot.data && snapshot.data.isNotEmpty) { tmpFiles = snapshot.data; base64Images = snapshot.data.map((file) => base64Encode(file.readAsBytesSync())).toList(); return Expanded( child: GridView.builder( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, crossAxisSpacing: 10, mainAxisSpacing: 10, ), itemCount: snapshot.data.length, itemBuilder: (context, index) { return Image.file( snapshot.data[index], fit: BoxFit.cover, ); }, ), ); } else if (null != snapshot.error) { return const Text( 'Error Picking Images', textAlign: TextAlign.center, ); } else { return const Text( 'No Images Selected', textAlign: TextAlign.center, ); } }, ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Upload Multiple Images Demo"), ), body: Container( padding: EdgeInsets.all(30.0), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: <Widget>[ OutlineButton( onPressed: chooseImages, child: Text('Choose Multiple Images'), ), SizedBox( height: 20.0, ), showImages(), SizedBox( height: 20.0, ), OutlineButton( onPressed: startUpload, child: Text('Upload All Images'), ), SizedBox( height: 20.0, ), Text( status, textAlign: TextAlign.center, style: TextStyle( color: Colors.green, fontWeight: FontWeight.w500, fontSize: 16.0, ), ), SizedBox( height: 20.0, ), ], ), ), ); } }
关键改动说明
- 变量类型调整:将单个
File相关的变量(file、tmpFile、base64Image)改为集合类型(List<File>、List<String>),用于存储多张图片的数据。 - 图片选择方法替换:使用
ImagePicker.pickMultiImage()替代pickImage(),支持一次性选择多张图片。 - 图片展示优化:用
GridView.builder替代单个Image.file,以网格形式展示选中的所有图片,更直观。 - 批量上传逻辑:循环遍历选中的图片列表,逐个调用上传接口;新增
uploadedCount变量跟踪上传进度,实时更新状态提示。 - 状态提示优化:状态文本会显示当前上传进度(如
Uploaded 2/5 images),全部完成后提示成功信息。
注意事项
- 确保你的后端接口
upload_image.php支持接收单张图片的上传请求,如果需要批量上传可进一步修改后端逻辑,将多张图片打包发送。 - 若需要处理大图片,建议在上传前添加图片压缩逻辑,避免上传超时或内存占用过高。
内容的提问来源于stack exchange,提问作者YourDeveloper
相关产品推荐
相关产品推荐

