Flutter file upload with Dio empty in Laravel

 ̄綄美尐妖づ 提交于 2021-02-08 10:12:36

问题


I'm unable to upload files using the Dio plugin and I can not figure out where's the problem. In Laravel the request is always empty.

What have I done so far:

  1. Double check if the file path really exists using existsSync() function
  2. Changed the Content-Type to application/x-www-form-urlencoded
  3. Validated if the file is actually being uploaded - seems yes (?)

This is my flutter code:

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

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

Before sending through POST i checked if the file exists and returns true

print(myFile.existsSync());

And set the Content-type properly

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

Printing the result of the form returns

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

Which I believe indicates that the file is being uploaded.

Now in laravel whenever i output the content received it always comes null the key file, but the key title comes with data.

The code print_r(json_encode($request->all())) retrieves

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

The same goes for print_r(json_encode($request->file('file'))).

What am i missing?


回答1:


Solved.

This took me a while to figure it out, but i end up realizing there's two problems with this approach:

  1. Laravel $request is empty, but $_FILES is not
  2. Sending multiple files can not be sent using arrays as the documentation tells

So, in order to achieve my goal which allows the user to select multiple files dynamically and upload them at the same time, here's the logic behind:

Flutter

The form must be created without setting the files right away:

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

Since the function .from is a Map<String, dynamic> values can be added after.

/* 
 * 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()));
}

There is no need to set up a different Content-Type, therefore this is enough:

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

Laravel / PHP

Forget about accessing the file through $request->file() and instead use the old school approach.

$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);
}



回答2:


I know this is an old post but this may help someone. this solution works for me, upload multi-file to server use Flutter Dio library and Laravel as backend. correct me if I did it wrong.

Flutter

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

For php resize image I use library 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);
}


来源:https://stackoverflow.com/questions/55478345/flutter-file-upload-with-dio-empty-in-laravel

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!