Laravel中Dio为空的情况下,文件颤动上传

时间:2019-04-02 15:24:17

标签: php laravel flutter

我无法使用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中,每当我输出接收到的内容时,键file总是为空,但是键title随数据一起提供。

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

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

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

我想念什么?

2 个答案:

答案 0 :(得分:0)

已解决。

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

  1. Laravel $request为空,但$_FILES不是
  2. 无法按照documentation的说明,使用数组发送多个文件

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

颤振

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

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

由于函数.fromMap<String, dynamic>,因此可以在后面添加值。

/* 
 * 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

忘记使用file来访问$request->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);
}

答案 1 :(得分:0)

我知道这是一篇旧文章,但这可能会对某人有所帮助。 此解决方案适用于我,使用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);
}