问题描述
是否可以将大文件上传到服务器?
我将MultipartRequest
与MultipartFile
一起使用,
List<int> fileBytes) async {
var request = new http.MultipartRequest("POST",Uri.parse(url));
request.files.add(http.MultipartFile.fromBytes(
'file',fileBytes,contentType: MediaType('application','octet-stream'),filename: fileName));
request.headers.addAll(headers);
var streamedResponse = await request.send();
return await http.Response.fromStream(streamedResponse);
并读取文件,如:
html.InputElement uploadInput = html.FileUploadInputElement();
uploadInput.multiple = false;
uploadInput.draggable = true;
uploadInput.click();
uploadInput.onChange.listen((e) {
final files = uploadInput.files;
final file = files[0];
final reader = new html.FileReader();
reader.onLoadEnd.listen((e) {
setState(() {
_bytesData =
Base64Decoder().convert(reader.result.toString().split(",").last);
_selectedFile = _bytesData;
});
});
reader.readAsDataUrl(file);
});
对于大约30 MB的文件来说还可以,但是超过Error code: Out of Memory
了。
我做错什么了吗?我看到某个地方
MultipartFile.fromBytes将给您更大文件带来一些问题,因为浏览器将限制您的内存消耗。
我认为他的解决方案是:
有一个fromStream构造函数。通常,对于较大的文件,我只使用HttpRequest,然后将File对象放在FormData实例中。
我使用了MultipartFile
和MultipartFile.fromString
,两次(对于150 MB的文件)都再次发生。
如何使用此解决方案?还是对于500 MB以上的文件有更好的方法?
更新
使用Worker
添加了答案。这不是一个很好的解决方案,但我希望这可以对某人有所帮助。如果您有更好/正确的解决方案,请告诉我们,我们将更改接受的答案。
解决方法
当前,我使用这种方法解决了问题:
导入:
fun fetchRemoteList(
url: String,context: Context,callback: OnFetchListCompleted,firstTry: Boolean = true
) {
val queue = Volley.newRequestQueue(context)
val stringRequest = StringRequest(
Request.Method.GET,url,Response.Listener { response ->
GlobalScope.launch {
callback.fetchListSucceed()
}
},Response.ErrorListener { error ->
val locationRedirectUrl: String? = error?.networkResponse?.headers?.get("Location")
if (firstTry && !locationRedirectUrl.isNullOrEmpty()) {
fetchRemoteList(locationRedirectUrl,context,callback,false)
} else {
callback.fetchListFailed(error?.message ?: "")
}
})
queue.add(stringRequest)
}
颤振部分:
import 'package:universal_html/html.dart' as html;
JavaScript部分:
在Web文件夹(在index.html旁边)中,创建文件'upload_worker.js'。
class Upload extends StatefulWidget {
@override
_UploadState createState() => _UploadState();
}
class _UploadState extends State<Upload> {
html.Worker myWorker;
html.File file;
_uploadFile() async {
String _uri = "/upload";
myWorker.postMessage({"file": file,"uri": _uri});
}
_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"),],);
}
}