Flutter网站:如何上传大文件?

问题描述

是否可以将大文件上传到服务器?

我将MultipartRequestMultipartFile一起使用,

  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了。

enter image description here

我做错什么了吗?我看到某个地方

MultipartFile.fromBytes将给您更大文件带来一些问题,因为浏览器将限制您的内存消耗。

我认为他的解决方案是:

有一个fromStream构造函数。通常,对于较大的文件,我只使用HttpRequest,然后将File对象放在FormData实例中。

我使用了MultipartFileMultipartFile.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"),],);
  }
}

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...