【问题标题】:Flutter file upload with Dio empty in Laravel在 Laravel 中,Dio 为空的 Flutter 文件上传
【发布时间】:2019-08-23 23:46:07
【问题描述】:

我无法使用Dio 插件上传文件,我不知道问题出在哪里。在 Laravel 中,请求总是空的。

到目前为止我做了什么:

  1. 使用existsSync()函数再次检查文件路径是否真的存在
  2. Content-Type 更改为application/x-www-form-urlencoded
  3. 验证文件是否正在上传 - 似乎是 (?)

这是我的颤振代码:

File myFile = new File('/storage/emulated/0/Download/demo.docx');

FormData form = new FormData.from({
  'title': 'Just testing',
  'file': new UploadFileInfo(myFile, 'demo.docx')
});

在通过POST发送之前,我检查了文件是否存在并返回true

print(myFile.existsSync());

并正确设置Content-type

Response response = await Dio().post(
  myUrl,
  data: form,
  options: new Options(
    contentType: ContentType.parse("application/x-www-form-urlencoded"),
  ),
);

打印form 返回的结果

I/flutter (27929): ----dio-boundary-0118165894
I/flutter (27929): Content-Disposition: form-data; name="title"

I/flutter (27929): ----dio-boundary-1759467036
I/flutter (27929): Content-Disposition: form-data; name="file"; filename="demo.docx"
I/flutter (27929): Content-Type: application/octet-stream

我认为这表明文件正在上传。

现在在 laravel 中,每当我输出接收到的内容时,它总是为 null 键 file,但键 title 带有数据。

代码print_r(json_encode($request->all()))检索

{"title":"Just testing","file":{}}

print_r(json_encode($request->file('file'))) 也是如此。

我错过了什么?

【问题讨论】:

  • 也许将文件内容解析为 base64 字符串,然后将该 base64 字符串发送到您的 API。
  • @DeesOomens 不能因为尺寸太大。

标签: php laravel flutter


【解决方案1】:

我知道这是一篇旧帖子,但这可能会对某人有所帮助。 这个解决方案对我有用,使用 Flutter Dio 库和 Laravel 作为后端将多文件上传到服务器。如果我做错了,请纠正我。

颤动

BaseOptions _dioOption({@required String token}) {
    BaseOptions options = new BaseOptions(baseUrl: baseUrl, headers: {
      Headers.acceptHeader: Headers.jsonContentType,
      Headers.contentTypeHeader: Headers.jsonContentType,
      "Authorization": "Bearer $token"
    });
    return options;   
}

  dioPostProduct( {@required ProductToUpload productToUpload,
                  @required String url, String token}) async {

    //productToUpload.images is a List<File>
    List<Object> filesData = new List<Object>();

    for (final file in productToUpload.images) {
      filesData.add(MultipartFile.fromFileSync(file.path,
          filename: file.path.split('/').last));
    }

    FormData data = FormData.fromMap({
      "subcategory_id": productToUpload.subcategory_id,
      "name": productToUpload.name,
      "detail": productToUpload.detail,
      "price": productToUpload.price,
      "condition_id": productToUpload.condition_id,
      "images": filesData,
    });

    Dio dio = new Dio(_dioOption(token: token));

    Response response;
    response = await dio.post(url, data: data);
    if (response.statusCode == 200) {
      print(response.data);
    }

  }

Laravel

对于 php 调整图像大小,我使用库 intervention
$images = Collection::wrap(request()->file('images'));
$directory = '/product_images'; //make sure directory is exist
foreach ($images as $image) {
   $basename = Str::random();
   $original = $basename . '.' . $image->getClientOriginalExtension();
   $thumbnail = $basename . '_thumb.' . $image->getClientOriginalExtension();
  Image::make($image)
  ->fit(400, 400)
  ->save(public_path($directory . '/' . $thumbnail));
  $image->move(public_path($directory), $original);
}

【讨论】:

    【解决方案2】:

    已解决。

    我花了一段时间才弄明白,但我最终意识到这种方法存在两个问题:

    1. Laravel $request 是空的,但 $_FILES 不是
    2. 不能像documentation 所说的那样使用数组发送多个文件

    所以,为了实现我的目标,即允许用户动态选择多个文件并同时上传,这是背后的逻辑:

    颤动

    必须在不立即设置文件的情况下创建表单:

    FormData form = new FormData.from(
    {
        'title': 'Just testing',
    });
    

    由于函数.fromMap&lt;String, dynamic&gt;,因此可以在其后添加值。

    /* 
     * files = List<String> containing all the file paths
     *
     * It will end up like this:
     *  file_1  => $_FILES
     *  file_2  => $_FILES 
     *  file_3  => $_FILES
     */
    for (int i = 0; i < files.length; i++) {
        form.add('file_' + i.toString(),
            new UploadFileInfo(new File(files[i]), files[i].toString()));
    }
    

    不需要设置不同的Content-Type,这样就足够了:

    Response response = await Dio().post(myUrl, data: form);
    

    Laravel / PHP

    忘记通过$request-&gt;file() 访问file,而是使用老式方法。

    $totalFiles = count($_FILES);
    
    for ($i = 0; $i < $totalFiles; $i++)
    {
        $file = $_FILES['file_' . $i];
    
        // handle the file normally ...
        $fileName       = basename($file['name']);
        $fileInfo       = pathinfo($file);
        $fileExtension = $fileInfo['extension'];
    
        move_uploaded_file($file['tmp_name'], $path);
    }
    

    【讨论】:

    • 嗨,我有同样的情况。我想从表单上传多张图片+文件。你能告诉我你是如何保存“文件”数组中的值的吗?我遇到“UploadFileInfo”类型的错误不是“String”类型的子类型。请让我知道,因为我没有找到任何关于此的帮助。谢谢
    • @FaranKhan files 是一个包含文件路径列表的字符串数组List&lt;String&gt; filePaths = [];
    猜你喜欢
    • 2020-12-27
    • 1970-01-01
    • 2021-01-01
    • 2018-02-04
    • 2020-08-11
    • 2020-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多