flutter web在实现大文件文件上传时受浏览器限制内存分配限制,需要用流的方式读入文件上传。
使用三方库 file_picker 进行文件选择
FilePickerResult? result = await FilePicker.platform.pickFiles(
allowMultiple: true,
withData: false,
withReadStream: true,
);
if(result == null){
return;
}
这里withData一定要设置为false,表示不返回文件数据。withReadStream一定设置为true,表示以流的方式读入数据。如果withData设置为true,会直接将选择文件数据一次性访问,如果文件稍微大一点浏览器就会报内存分配失败。
上传文件
使用http package 来实现文件上传,在pubspec.yaml 文件中引入http
dependencies:
http: ^1.2.1
或者运行如下命令
$ flutter pub add http
文件上传代码
import 'package:http/http.dart' as http;
for(var f in result.files) async{
//上传文件URL
String apiurl = "https://xxx.xxx.xxx/upload";
String response = await uploadFile(apiurl, f);
print(response);
}
uploadFile(String uploadurl, PlatformFile f) async{
final request = http.MultipartRequest("POST", Uri.parse(uploadurl));
//设置post请求Headers,比如认证信息
request.headers['authtoken'] = “xxxxx";
//将文件流参数传递给MultipartFile
request.files
.add(http.MultipartFile("file", f.readstream!, f.size, filename: f.name));
//调用send方法发送post请求
var resp = await request.send();
//等待上传完成返回结果
String result = await resp.stream.bytesToString();
return result;
}
可以在MultipartRequest中监听上传进度
final request = http.MultipartRequest(
“POST”,
Uri.parse(uploadurl),
onProgress: (int bytes, int total) {
final progress = bytes / total;
print(‘progress: $progress ($bytes/$total)’);
},
);
这个进度是发送数据的进度,而不是真是上传的进度,结果就是现实上传已经完成,其实真是的上传还没有结束。
代码能用,怎么实现上传进度监控呢
可以参考这篇文章
https://stackoverflow.com/questions/70079208/how-to-upload-large-files-in-flutter-web
可以用Dio来实现上传监控:
dio.post(url,
data: formData, options: Options(headers: header),
onSendProgress: (int count, int total)
onSendProgress里面的count就是已上传的大小,total就是文件总大小。
好像dio不支持Web
dio 3.0以后支持web了