![](/img/trans.png)
[英]Flutter upload large file with progress bar. App and Web both support
[英]Flutter Web multipart formdata file upload progress bar
我正在使用 Flutter web 和 strapi 無頭 cms 作為后端。 我能夠成功發送文件,但想要它的進度指示。 后端限制:文件上傳必須是多部分表單數據,可以是緩沖區或 stream。 前端限制: Flutter web 無權訪問系統文件目錄; 文件必須在 memory 中加載並使用其字節發送。
我可以使用顫振的 http package 或 Dio package 上傳文件,但是在嘗試以某種方式訪問上傳進度時出現以下問題:
Http 示例代碼:
http.StreamedResponse response;
final uri = Uri.parse(url);
final request = MultipartRequest(
'POST',
uri,
);
request.headers['authorization'] = 'Bearer $_token';
request.files.add(http.MultipartFile.fromBytes(
'files',
_fileToUpload.bytes,
filename: _fileToUpload.name,
));
response = await request.send();
var resStream = await response.stream.bytesToString();
var resData = json.decode(resStream);
我嘗試了什么:當訪問 onData 的 response.stream 時,它僅在服務器發送完成的請求時響應(即使方法聲明它應該獲得一些進度指示)。
迪歐package代碼
Response response = await dio.post(url,
data: formData,
options: Options(
headers: {
'authorization': 'Bearer $_token',
},
), onSendProgress: (int sent, int total) {
setState(() {
pm.progress = (sent / total) * 100;
});
問題:
It seems the package is able to get some progress indication, but Dio package for flutter web has a bug which has not been fixed: requests block the ui and the app freezes until upload is finished.
您好,您可以使用universal_html/html.dart package來做進度條,步驟如下:
import 'package:universal_html/html.dart' as html;
_selectFile() {
html.FileUploadInputElement uploadInput = html.FileUploadInputElement();
uploadInput.multiple = false;
uploadInput.accept = '.png,.jpg,.glb';
uploadInput.click();
uploadInput.onChange.listen((e) {
_file = uploadInput.files.first;
});
}
self.addEventListener('message', async (event) => {
var file = event.data.file;
var url = event.data.url;
var postData = event.data.postData;
uploadFile(file, url, postData);
});
function uploadFile(file, url, presignedPostData) {
var xhr = new XMLHttpRequest();
var formData = new FormData();
Object.keys(presignedPostData).forEach((key) => {
formData.append(key, presignedPostData[key]);
});
formData.append('Content-Type', file.type);
// var uploadPercent;
formData.append('file', file);
xhr.upload.addEventListener("progress", function (e) {
if (e.lengthComputable) {
console.log(e.loaded + "/" + e.total);
// pass progress bar status to flutter widget
postMessage(e.loaded/e.total);
}
});
xhr.onreadystatechange = function () {
if (xhr.readyState == XMLHttpRequest.DONE) {
// postMessage("done");
}
}
xhr.onerror = function () {
console.log('Request failed');
// only triggers if the request couldn't be made at all
// postMessage("Request failed");
};
xhr.open('POST', url, true);
xhr.send(formData);
}
class Upload extends StatefulWidget {
@override
_UploadState createState() => _UploadState();
}
class _UploadState extends State<Upload> {
html.Worker myWorker;
html.File file;
_uploadFile() async {
String _uri = "/upload";
final postData = {};
myWorker.postMessage({"file": file, "uri": _uri, postData: postData});
}
_selectFile() {
html.InputElement uploadInput = html.FileUploadInputElement();
uploadInput.multiple = false;
uploadInput.click();
uploadInput.onChange.listen((e) {
file = uploadInput.files.first;
});
}
@override
void initState() {
myWorker = new html.Worker('upload_worker.js');
myWorker.onMessage.listen((e) {
setState(() {
//progressbar,...
});
});
super.initState();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
RaisedButton(
onPressed: _selectFile,
child: Text("Select File"),
),
RaisedButton(
onPressed: _uploadFile,
child: Text("Upload"),
),
],
);
}
}
就是這樣,我希望它可以幫助你。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.