【问题标题】:How to upload images to server in Flutter?如何在 Flutter 中将图像上传到服务器?
【发布时间】:2017-12-04 03:13:46
【问题描述】:

我想上传一张图片,我正在使用 http.Client() 发出请求,

static uploadImage(String id, File file) {
  var httpClient = createHttpClient();

  Map<String, String> headers = new Map<String, String>();
  headers.putIfAbsent("Authorization", () => "---");
  headers.putIfAbsent("Content-Type", () => "application/json");

  var body=new List();
  body.add(id.)
  httpClient.post(URL_UPLOADIMAGE,headers: headers,body: ,encoding: )
}

请求的正文和编码部分应该是什么?

【问题讨论】:

  • 您应该可以使用与dart question相同的方法!
  • 做到了,但是答案来自旧版本的库。
  • request.files.add(new http.MultipartFile.fromBytes("file", file.readAsBytesSync(), filename: "Photo.jpg", contentType: new MediaType("image", "jpg "))); //现在可以了。
  • 遇到同样的问题,你会分享你的解决方案吗?
  • @karanvs :- 我想添加更多,如何添加其他参数与此和用户注册表数据,如何添加,你能举个例子

标签: flutter dart file-upload multipartform-data multipart


【解决方案1】:

使用MultipartRequest

Upload(File imageFile) async {    
    var stream = new http.ByteStream(DelegatingStream.typed(imageFile.openRead()));
      var length = await imageFile.length();

      var uri = Uri.parse(uploadURL);

     var request = new http.MultipartRequest("POST", uri);
      var multipartFile = new http.MultipartFile('file', stream, length,
          filename: basename(imageFile.path));
          //contentType: new MediaType('image', 'png'));

      request.files.add(multipartFile);
      var response = await request.send();
      print(response.statusCode);
      response.stream.transform(utf8.decoder).listen((value) {
        print(value);
      });
    }

命名空间:

import 'package:path/path.dart';
import 'package:async/async.dart';
import 'dart:io';
import 'package:http/http.dart' as http;

【讨论】:

  • 我上传的文件总是application/octet-stream。有没有办法从文件中获取正确的内容类型以及如何在请求中设置它?
  • 从哪里导入 MediaType 类
  • 我想我只需要import 'package:http_parser/http_parser.dart';
  • DelegatingStream.typed 已弃用。
  • 使用var stream = new http.ByteStream(_image.openRead()); stream.cast();代替DelegatingStream.typed
【解决方案2】:

最简单的方法是使用http库,

import 'dart:io';
import 'package:http/http.dart' as http;

_asyncFileUpload(String text, File file) async{
   //create multipart request for POST or PATCH method
   var request = http.MultipartRequest("POST", Uri.parse("<url>"));
   //add text fields
   request.fields["text_field"] = text;
   //create multipart using filepath, string or bytes
   var pic = await http.MultipartFile.fromPath("file_field", file.path);
   //add multipart to request
   request.files.add(pic);
   var response = await request.send();

   //Get the response from the server
   var responseData = await response.stream.toBytes();
   var responseString = String.fromCharCodes(responseData);
   print(responseString);
}

【讨论】:

  • 你好,它给了我 Unhandled Exception: SocketException: OS Error: Broken pipe, errno = 32 ,请建议
  • 请检查网址。确保您能够从 Postman 发布您的文件数据
  • 如何在我的 .php 文件中接收它?
  • 我不太擅长 PHP 但你可以使用 $_FILES["file_field"]
  • @Santiago 如果来不及回答你,那么它可以帮助其他人。在我的服务器端,我接受它作为 HTML 表单中的普通文件,一切顺利。
【解决方案3】:

submitForm() 方法中检查正文。

File _image;

Future cameraImage() async {
  var image = await ImagePicker.pickImage(
    source: ImageSource.camera,
    maxHeight: 240.0,
    maxWidth: 240.0,
  );

  setState(() {
    _image = image;
  });
}

submitForm() async {
  final response = await http.post(
    uri,
    headers: {
      AuthUtils.AUTH_HEADER: _authToken
    },
    body: {
      'user_id': userId
      'photo': _image != null ? 'data:image/png;base64,' +
          base64Encode(_image.readAsBytesSync()) : '',
    },
  );

  final responseJson = json.decode(response.body);

  print(responseJson);
}

【讨论】:

  • 如何在我的 .php 文件中接收它?
  • @Santiago 您需要解码并保存。你可以在这里找到解决方案stackoverflow.com/questions/11511511/…
  • Base64 很简单,但带宽非常昂贵...要发送的数据最多增加 30%...不推荐
【解决方案4】:

我已经尝试了以上所有方法,但没有一个适合我将文件上传到服务器。

经过深度搜索,得到一个和Dio一样的插件。

以下代码将文件上传到服务器。

uploadFileFromDio(UserProfile userProfile, File photoFile) async {
    var dio = new Dio();
    dio.options.baseUrl = url;
    dio.options.connectTimeout = 5000; //5s
    dio.options.receiveTimeout = 5000;
    dio.options.headers = <Header Json>;
    FormData formData = new FormData();
    formData.add("user_id", userProfile.userId);
    formData.add("name", userProfile.name);
    formData.add("email", userProfile.email);

    if (photoFile != null &&
        photoFile.path != null &&
        photoFile.path.isNotEmpty) {
      // Create a FormData
      String fileName = basename(photoFile.path);
      print("File Name : $fileName");
      print("File Size : ${photoFile.lengthSync()}");
      formData.add("user_picture", new UploadFileInfo(photoFile, fileName));
    }
    var response = await dio.post("user/manage_profile",
        data: formData,
        options: Options(
            method: 'POST',
            responseType: ResponseType.PLAIN // or ResponseType.JSON
            ));
    print("Response status: ${response.statusCode}");
    print("Response data: ${response.data}");
  }

【讨论】:

  • 您对内容类型有任何问题吗?如果我上传图片,我必须手动设置内容类型。
  • "content-type" 基本上是在 api 的 header 中设置的,所以你必须添加一个 header 参数作为 content-type 无论 api 开发人员在那里设置什么内容类型的一些常见示例是“text/plain ”、“application/xml”、“text/html”、“application/json”、“image/gif”和“image/jpeg”。
  • 我正在将文件(图像、文档等)从移动设备发送到 Node.js API,它使用 multer 将文件存储到 MongoDB。我还有一个与相同 API 通信的 Web 应用程序。如果我通过我的移动应用程序和 Dio 插件上传图像,服务器和我的 mobgodb 中的 mime 类型是“application/octet-stream”。如果我通过我的网络应用程序上传它,mime 类型是“image/jpeg”。我不需要在我的网络应用中手动设置内容类型。
  • 我正在将图像上传到服务器,但是当我尝试打开一个图像时说图像是空的?
  • 如何在我的 .php 文件中接收它?
【解决方案5】:

考虑使用 Flutter 的 Firebase Storage plugin——它具有可用于在移动连接上上传大图像文件的功能。

插件是我写的,欢迎投稿和反馈!

【讨论】:

  • 谢谢,我可以用 http 客户端库做到这一点
  • “使用 Firebase 插件(我写的)”不是“如何在 Flutter 中上传图片?”的答案。
【解决方案6】:

我找到了一个不使用任何外部插件的工作示例,这个 只使用

import 'package:http/http.dart' as http;

代码

var stream =
        new http.ByteStream(DelegatingStream.typed(imageFile.openRead()));
    // get file length
    var length = await imageFile.length(); //imageFile is your image file
    Map<String, String> headers = {
      "Accept": "application/json",
      "Authorization": "Bearer " + token
    }; // ignore this headers if there is no authentication

    // string to uri
    var uri = Uri.parse(Constants.BASE_URL + "api endpoint here");

    // create multipart request
    var request = new http.MultipartRequest("POST", uri);

  // multipart that takes file
    var multipartFileSign = new http.MultipartFile('profile_pic', stream, length,
        filename: basename(imageFile.path));

    // add file to multipart
    request.files.add(multipartFileSign);

    //add headers
    request.headers.addAll(headers);

    //adding params
    request.fields['loginId'] = '12';
    request.fields['firstName'] = 'abc';
   // request.fields['lastName'] = 'efg';

    // send
    var response = await request.send();

    print(response.statusCode);

    // listen for response
    response.stream.transform(utf8.decoder).listen((value) {
      print(value);

    });

【讨论】:

  • 当我使用你的代码时,它给了我一个错误说"image":["No file was submitted."]。关于如何解决这个问题的任何想法?
【解决方案7】:

请尝试以下解决方案

Future<String> uploadImageHTTP(file, url) async {

  var request = http.MultipartRequest('POST', Uri.parse(url));
  request.files.add(await http.MultipartFile.fromPath('picture', file.path));
  var res = await request.send();
  return res.reasonPhrase;

}

【讨论】:

  • 我收到了这个错误。 “字符串?”类型的值无法从函数“uploadImageHTTP”返回,因为它的返回类型为“Future”。
  • 考虑空安全更改
【解决方案8】:

首先从图库或相机中选择您的图像

File _image;
Future _getImage() async {
var image = await ImagePicker.pickImage(source: ImageSource.gallery);
setState(() {
_image = image;
});
}

现在在按钮单击或 _getImage() 函数内部调用以下函数。使用我正在上传其他字段的文件,您也会在 saveInAttendance() 中看到

别忘了导入包:

import 'package:dio/dio.dart';
import 'package:path/path.dart';

Future saveInAttendance( BuildContext context,String entryType,String mode) async {
        Dio dio = new Dio();
        FormData formData = new FormData(); // just like JS
        formData.add("inimageFile", new UploadFileInfo(_image, basename(_image.path)));
        formData.add("compID",2);
        formData.add("company_id",2);
        formData.add("EntryType", entryType);
        formData.add("emp_code", 5);
        formData.add("Mode",mode);
        formData.add("location",""+_startLocation.latitude.toString()+"-"+_startLocation.longitude.toString());
        dio.post(url_save_attendance, data: formData, options: Options(
            method: 'POST',
            responseType: ResponseType.json // or ResponseType.JSON
        ))
            .then((r) {
          setState(() {
            var data = json.decode(r.toString());
            if(data["apiMessage"].contains('Saved')){
              warningAlert("Attendance Saved", "Your attendance saved Successfully",context);
            }
          });
        }).catchError(print);
      }

更多信息您可以访问Here

【讨论】:

    【解决方案9】:

    下面我的工作代码,基于@TejaDroid's sample, 它通过 AWS Gateway API 上传一张图片,后面带有一个 lambda 函数,以将图片存储到 S3 中。

    uploadImageWithhttp(File imageFile, int serialno) async {
        var postBody= {
            'username': 'test@gmail.com',  
            "productid": "1000123",             //TODO
            "imageno": serialno.toString(), 
            'image': imageFile != null ? base64Encode(imageFile.readAsBytesSync()) : '',
        };
    
        final response = await http.post(
          constAWSAPIGateway_UploadImage[CONST_API_STAGE],
          headers: {
            //AuthUtils.AUTH_HEADER: _authToken
            'Content-Type' : 'application/json',
          },
          body: json.encode(postBody),
        );
    
        final responseJson = json.decode(response.body);
    
        print(responseJson);
      }
    

    【讨论】:

      【解决方案10】:

      从请求中获取正文而不是

      response.stream.transform(utf8.decoder).listen((value) {
          print(value);
        });
      

      我用:

      String body=await response.stream.bytesToString()
      

      【讨论】:

        【解决方案11】:

        导入dio,image_picker

            Future _onGalleryPressed() async {
                    Future<File> image = ImagePicker.pickImage(source: ImageSource.gallery);
                    setState(() {
                      this._imageFile = image;
                    });
                    File img = await image;
                    Navigator.of(context).pop();
                    if (img != null) {
                      //API CALL
                      try {
                        FormData formData = new FormData.from({"file": path});
                        var url = backendUrl + "/upload-image";
                        var token = await _getMobileToken();
                        Map<String, String> headers = {
                          'Authorization': 'Bearer $token',
                          "Content-Type": "multipart/form-data",
                          "X-Requested-With": "XMLHttpRequest"
                        };
                        await dio.post(url,
                          data: formData,
                          options: Options(
                              method: 'POST',
                              headers: headers,
                              responseType: ResponseType.json // or ResponseType.JSON
                              ));
                        Navigator.pop(context);
                      } catch (e) {}
                    }
                  }
        

        【讨论】:

        • 如何在我的 .php 文件中接收它?
        【解决方案12】:

        如果您想将其作为二进制文件上传。

          static uploadFile(File imageFile) async {
            final response = await http.post(postURL, body: imageFile.readAsBytesSync());
            return json.decode(response.body);
          }
        

        谢谢

        【讨论】:

          【解决方案13】:
          updateProfile() async {
                  try {
                    if (_formKey.currentState.validate()) {
                      _formKey.currentState.save();
                      var dio = new Dio();
                      var formData = FormData.fromMap({
                        'name': name,
                        'con_person_name': concernedPersonName,
                        'email': email,
                        'phone': phoneNumber,
                        'password': password,
                        'token': token,
                        'user_type': '3',
                        'license_no': licenceNumber,
                        'gstno': gstNumber,
                        'address': address,
                        'hospital_id': '102'
                        'image': await MultipartFile.fromFile(_image?.path,
                      filename: _image.path.split('/').last ?? 'image.jpeg'),
                     
                      });
                      var response = await dio.post('$SERVER_ADDRESS/api/doctorregister',
                          data: formData);
                      print(response.statusCode);
                      print(response.data);
                    }
                  } catch (error) {
                    print(error.toString());
                  }
                }
          

          【讨论】:

          • 请连同您的答案一起。提供解释
          【解决方案14】:

          我在多个地方检查过,终于找到了解决方案-

                              var objToSend = {
                                    "file": await MultipartFile.fromFile(
                                          file.path,
                                          filename: filename,
                                       ),
                              };
          
                              FormData formData = FormData.fromMap(objToSend);
                             
                              print(formData.files.toString());
                              Dio dio = new Dio();
          
                              await dio
                                  .post(_toSend,
                                      data: formData,
                                      options: Options(
                                         method: 'POST',
                                         headers: <String, String>{
                                            "Content-Type": "application/json",
                                            "Access-Control-Allow-Origin": "*",
                                            "Authorization": 'Bearer ' + token
                                           },
                                      ))
                                  .whenComplete(() {
                                       print('uploaded');
                                   }).catchError((onError) {
                                       print('failed');
                                   });
          

          【讨论】:

            猜你喜欢
            • 2021-01-18
            • 1970-01-01
            • 2018-08-13
            • 2021-02-27
            • 1970-01-01
            • 2020-03-15
            • 1970-01-01
            相关资源
            最近更新 更多