Flutter Retrofit上传多部分抛出415不支持的媒体类型

agxfikkp  于 2023-02-25  发布在  Flutter
关注(0)|答案(1)|浏览(382)

我试图上传一个图像使用多部分从Flutter改造使用此代码

@POST("apiUrl/upload/files")
  @MultiPart()
  Future<TSSuccessResponse<UploadFileRemoteResponse>> uploadFile(
      @Part() File file);

然而,它不断得到错误415,说应用程序/形式八位字节是不支持的媒体类型。

E/flutter ( 8367): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: DioError [bad response]: The request returned an invalid status code of 415.
E/flutter ( 8367): #0      DioMixin.fetch.<anonymous closure> (package:dio/src/dio_mixin.dart:530:7)
E/flutter ( 8367): #1      _RootZone.runBinary (dart:async/zone.dart:1665:54)
E/flutter ( 8367): #2      _FutureListener.handleError (dart:async/future_impl.dart:162:22)
E/flutter ( 8367): #3      Future._propagateToListeners.handleError (dart:async/future_impl.dart:779:47)
E/flutter ( 8367): #4      Future._propagateToListeners (dart:async/future_impl.dart:800:13)
E/flutter ( 8367): #5      Future._completeError (dart:async/future_impl.dart:575:5)
E/flutter ( 8367): #6      _SyncCompleter._completeError (dart:async/future_impl.dart:51:12)
E/flutter ( 8367): #7      _Completer.completeError (dart:async/future_impl.dart:23:5)
E/flutter ( 8367): #8      Future.any.onError (dart:async/future.dart:617:45)
E/flutter ( 8367): #9      _RootZone.runBinary (dart:async/zone.dart:1665:54)
E/flutter ( 8367): #10     _FutureListener.handleError (dart:async/future_impl.dart:162:22)
E/flutter ( 8367): #11     Future._propagateToListeners.handleError (dart:async/future_impl.dart:779:47)
E/flutter ( 8367): #12     Future._propagateToListeners (dart:async/future_impl.dart:800:13)
E/flutter ( 8367): #13     Future._completeError (dart:async/future_impl.dart:575:5)
E/flutter ( 8367): #14     Future._asyncCompleteError.<anonymous closure> (dart:async/future_impl.dart:666:7)
E/flutter ( 8367): #15     _microtaskLoop (dart:async/schedule_microtask.dart:40:21)
E/flutter ( 8367): #16     _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5)

I/flutter ( 8367): ╔ DioErrorType.badResponse
I/flutter ( 8367): ║    {
I/flutter ( 8367): ║         statusCode: 415,
I/flutter ( 8367): ║         "File type application/octet-stream is not matching: image, pdf, powerpoint, prese
I/flutter ( 8367): ║         ntation, video, video/quicktime"
I/flutter ( 8367): ║         error: "Unsupported Media Type"
I/flutter ( 8367): ║    }
I/flutter ( 8367): ╚══════════════════════════════════════════════════════════════════════════════════════════╝

然后,我尝试更改请求,在@Part()标记中包含content-type,以便它满足从Retrofit生成的文件。

@POST("apiUrl/upload/files")
  @MultiPart()
  Future<TSSuccessResponse<UploadFileRemoteResponse>> uploadFile(
      @Part(contentType: "image/png") File file);

但是它抛出另一个错误,即

E/flutter ( 8367): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: DioError [bad response]: The request returned an invalid status code of 415.
E/flutter ( 8367): #0      DioMixin.fetch.<anonymous closure> (package:dio/src/dio_mixin.dart:530:7)
E/flutter ( 8367): #1      _RootZone.runBinary (dart:async/zone.dart:1665:54)
E/flutter ( 8367): #2      _FutureListener.handleError (dart:async/future_impl.dart:162:22)
E/flutter ( 8367): #3      Future._propagateToListeners.handleError (dart:async/future_impl.dart:779:47)
E/flutter ( 8367): #4      Future._propagateToListeners (dart:async/future_impl.dart:800:13)
E/flutter ( 8367): #5      Future._completeError (dart:async/future_impl.dart:575:5)
E/flutter ( 8367): #6      _SyncCompleter._completeError (dart:async/future_impl.dart:51:12)
E/flutter ( 8367): #7      _Completer.completeError (dart:async/future_impl.dart:23:5)
E/flutter ( 8367): #8      Future.any.onError (dart:async/future.dart:617:45)
E/flutter ( 8367): #9      _RootZone.runBinary (dart:async/zone.dart:1665:54)
E/flutter ( 8367): #10     _FutureListener.handleError (dart:async/future_impl.dart:162:22)
E/flutter ( 8367): #11     Future._propagateToListeners.handleError (dart:async/future_impl.dart:779:47)
E/flutter ( 8367): #12     Future._propagateToListeners (dart:async/future_impl.dart:800:13)
E/flutter ( 8367): #13     Future._completeError (dart:async/future_impl.dart:575:5)
E/flutter ( 8367): #14     Future._asyncCompleteError.<anonymous closure> (dart:async/future_impl.dart:666:7)
E/flutter ( 8367): #15     _microtaskLoop (dart:async/schedule_microtask.dart:40:21)
E/flutter ( 8367): #16     _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5)

I/flutter ( 8367): ╔ DioErrorType.badResponse
I/flutter ( 8367): ║    {
I/flutter ( 8367): ║         statusCode: 415,
I/flutter ( 8367): ║         message: "File type is not matching",
I/flutter ( 8367): ║         error: "Unsupported Media Type"
I/flutter ( 8367): ║    }
I/flutter ( 8367):

我还尝试将contentType更改为“image/*”,但它在MediaType.parser(从生成的文件)上抛出错误,说这是一个无效的类型。
在这个场景中我错过了什么吗?以前有人解决过这个问题吗?我尝试了1(https://stackoverflow.com/questions/57509972/flutter-dio-how-to-upload-image),2(https://stackoverflow.com/questions/60594063/flutter-dio-upload-files-pdf-docs)和其他许多人提到的解决方案,但仍然卡在这个问题上。

有一点需要注意:此请求在Postman中对相同文件正常工作。

zfciruhq

zfciruhq1#

我已经找到了问题的答案。有人在github中提出了这个问题,显然问题的根本原因是Dio将MediaType设置为application/octet-stream,而我们没有指定任何MediaType。
如果我们像这样从改型中指定它(通过@Part的contentType),

@POST("apiUrl/upload/files")
  @MultiPart()
  Future<TSSuccessResponse<UploadFileRemoteResponse>> uploadFile(
      @Part(contentType: "image/jpg") File file);

从Retrofit生成的文件中的以下行仍将抛出错误,因为它与模式不匹配。

MediaType.parse(contentType)

我的解决方案是使用普通的Dio请求,然后按照前面的github链接的建议,使用www.example.com上的mime包指定mime类型pub.dev。

import 'package:mime/mime.dart';

    FormData data = FormData.fromMap({
      "file": await MultipartFile.fromFile(file.path,
          filename: fileName,
          contentType: MediaType.parse("${lookupMimeType(fileName)}")),
    });

    final response = await dio.post(
      "api/uploadFile",
      data: data,
      options: Options(headers: {"Content-Type": "multipart/form-data"}),
    );

相关问题