Flutter 上传带有进度条的大文件。 App 和 Web 都支持
Posted
技术标签:
【中文标题】Flutter 上传带有进度条的大文件。 App 和 Web 都支持【英文标题】:Flutter upload large file with progress bar. App and Web both support 【发布时间】:2021-06-23 04:49:49 【问题描述】:我遇到上传大文件的问题。当从应用程序上传文件工作正常但网络挂起时,为 Web 和应用程序(本机)编译的颤振应用程序。如何将大文件作为流请求发送。
我是 Flutter 的新手,正在开发当前现有的应用程序,该应用程序具有上传大型教程视频文件和 PDF 文件的功能。要求是在上传文件的过程中显示进度条,目前应用程序我使用了dio
,但它在网页版中挂起,而不是文件不上传操作失败。
目前使用以下包
dependencies:
http: ^0.12.2
dio: ^3.0.10
你能帮我解决这个问题吗?
我正在尝试使用以下代码来实现,但有些代码无法正常工作。 https://github.com/salk52/Flutter-File-Upload-Download
抛出“内存缓冲区分配失败”之类的错误,由于其他包干扰,我无法更新dio
或http的版本。不知何故,我必须使用httpclient
或dio
来实现它。我无法更新包的版本,因为它弄乱了其他包的依赖关系。
示例参考。代码如下: 文件大小约为 500 MB 到 700MB
对于参考。以下代码在代码中使用。
Dio封装示例:
#Dio example start
Future<NormalResponse> addSubjectMaterial(
GetSubjectMaterial objSubMat,
bool isDelete,
PlatformFile objfile,
Function sendProgress,
Function receiveProgress,
dio.CancelToken cancelToken) async
NormalResponse objRes = NormalResponse();
try
print(objSubMat.objMaterial.subjectId);
dio.FormData formData = dio.FormData();
formData.fields.add(MapEntry("ObjSubMat", json.encode(objSubMat)));
formData.fields.add(MapEntry("IsDelete", isDelete.toString()));
formData.fields
.add(MapEntry("ClassesId", AppConstants.classesId().toString()));
if (objfile != null)
formData.files.add(
MapEntry("objfile", await getMultipartFile(objfile, "objfile")));
var resp = await dio.Dio().post(
AppConstants.addUpdateSubjectMaterial,
data: formData,
options: requestConfig,
cancelToken: cancelToken,
onSendProgress: sendProgress,
onReceiveProgress: receiveProgress,
);
// String respStr = resp.toString();
// objRes = NormalResponse.fromJson(json.decode(respStr));
objRes = NormalResponse.fromJson(resp.data);
catch (err)
objRes.err = err.toString();
objRes.isSuccess = false;
objRes.newId = -1;
sendProgress = null;
receiveProgress = null;
return objRes;
#Dio example end
#httpclient example code is there any solution with progress bar in this sample code.
Future<NormalResponse> addUpdateSubjectMaterialHttp(
GetSubjectMaterial objSubMat,
bool isDelete,
PlatformFile objfile,
Function sendProgress,
Function receiveProgress,
dio.CancelToken cancelToken) async
NormalResponse objRes = NormalResponse();
try
var req = http.MultipartRequest(
"POST",
Uri.parse(AppConstants.addUpdateSubjectMaterial),
);
req.headers.addAll(
'Content-type': 'application/json',
'Accept': 'application/json',
);
req.fields['ObjSubMat'] = json.encode(objSubMat);
req.fields['IsDelete'] = isDelete.toString();
req.fields['ClassesId'] = AppConstants.classesId().toString();
if (objfile != null)
req.files.add(http.MultipartFile(
"objFile", objfile.readStream, objfile.size,
filename: objfile.name));
var resp = await req.send();
String result = await resp.stream.bytesToString();
objRes = NormalResponse.fromJson(json.decode(result));
print(objRes.isSuccess);
print(objRes.err);
print("Here done");
catch (err)
print(err);
throw err;
return objRes;
#httpclient
Http package example:
#example start
Future<NormalResponse> addSubjectMaterial(
GetSubjectMaterial objSubMat,
bool isDelete,
PlatformFile objfile,
Function sendProgress,
Function receiveProgress,
dio.CancelToken cancelToken) async
NormalResponse objRes = NormalResponse();
try
print(objSubMat.objMaterial.subjectId);
dio.FormData formData = dio.FormData();
formData.fields.add(MapEntry("ObjSubMat", json.encode(objSubMat)));
formData.fields.add(MapEntry("IsDelete", isDelete.toString()));
formData.fields
.add(MapEntry("ClassesId", AppConstants.classesId().toString()));
if (objfile != null)
formData.files.add(
MapEntry("objfile", await getMultipartFile(objfile, "objfile")));
var resp = await dio.Dio().post(
AppConstants.addUpdateSubjectMaterial,
data: formData,
options: requestConfig,
cancelToken: cancelToken,
onSendProgress: sendProgress,
onReceiveProgress: receiveProgress,
);
// String respStr = resp.toString();
// objRes = NormalResponse.fromJson(json.decode(respStr));
objRes = NormalResponse.fromJson(resp.data);
catch (err)
objRes.err = err.toString();
objRes.isSuccess = false;
objRes.newId = -1;
sendProgress = null;
receiveProgress = null;
return objRes;
#example end
【问题讨论】:
【参考方案1】:您必须使用 Future、await 和 async,它们在后台线程中继续流的任务,同时您的应用程序的 UI 工作顺利。
【讨论】:
能否提供一些示例代码。 好的@DharmeshChauhan 我正在编辑我的答案,但请回复您使用什么来存储数据,firebase 或其他任何东西或 mysql 您好 Manav,感谢您的回复。我正在使用 API 调用它。在 App 版本中,它也可以与简单的 html 页面一起正常工作。 @DharmeshChauhan 当我通读您的代码时,您似乎已经正确地实现了所有的东西。我有一个建议为 web 构建一个版本,然后尝试,因为您正在尝试调试模式。谢谢。以上是关于Flutter 上传带有进度条的大文件。 App 和 Web 都支持的主要内容,如果未能解决你的问题,请参考以下文章
带有进度条的 jQuery ajax 上传 - 没有 flash
Alamofire 上传带有进度的大文件并在应用重启时显示进度