multipartRequest static method

dynamic multipartRequest({
  1. required Uri url,
  2. Map<String, String>? headers,
  3. Map<String, Map<String, dynamic>>? files,
  4. Map<String, String>? fields,
})

Http multipart request for file uploads Example:

final result = await PackageHttp.multipartRequest(
  url: uri,
  files: {
    'image': {
      'path': '/path/to/image.jpg',
      'filename': 'image.jpg',
    },
  },
  fields: {
    'title': 'My Image',
    'description': 'Image description',
  },
);

Implementation

/// Example:
/// ```dart
/// final result = await PackageHttp.multipartRequest(
///   url: uri,
///   files: {
///     'image': {
///       'path': '/path/to/image.jpg',
///       'filename': 'image.jpg',
///     },
///   },
///   fields: {
///     'title': 'My Image',
///     'description': 'Image description',
///   },
/// );
/// ```
static multipartRequest({
  required Uri url,
  Map<String, String>? headers,
  Map<String, Map<String, dynamic>>? files,
  Map<String, String>? fields,
}) async {
  try {
    final prepared = await UnifiedInterceptorRunner.runOnRequest(
      UnifiedRequest(method: 'POST', uri: url, headers: headers, body: {'files': files, 'fields': fields}),
      _interceptors,
    );

    debugPrint('requesting multipart : ${prepared.uri}');
    final request = http.MultipartRequest('POST', prepared.uri);

    // Add headers if provided
    if (prepared.headers.isNotEmpty) {
      request.headers.addAll(prepared.headers);
    }

    final processedBody = prepared.body is Map<String, dynamic> ? prepared.body as Map<String, dynamic> : <String, dynamic>{};
    final processedFields = (processedBody['fields'] ?? fields) as Map<String, String>?;
    final processedFiles = (processedBody['files'] ?? files) as Map<String, Map<String, dynamic>>?;

    // Add form fields
    if (processedFields != null) {
      request.fields.addAll(processedFields);
    }

    // Add files
    if (processedFiles != null) {
      for (final entry in processedFiles.entries) {
        final fieldName = entry.key;
        final fileData = entry.value;

        http.MultipartFile multipartFile;

        if (fileData.containsKey('path')) {
          // File from path
          final filePath = fileData['path'] as String;
          final filename = fileData['filename'] as String? ?? filePath.split('/').last;
          final contentTypeStr = fileData['contentType'] as String?;

          if (contentTypeStr != null) {
            final file = File(filePath);
            final bytes = await file.readAsBytes();
            multipartFile = http.MultipartFile(
              fieldName,
              Stream.value(bytes),
              bytes.length,
              filename: filename,
              contentType: http.MediaType.parse(contentTypeStr),
            );
          } else {
            multipartFile = await http.MultipartFile.fromPath(
              fieldName,
              filePath,
              filename: filename,
            );
          }
        } else if (fileData.containsKey('bytes')) {
          // File from bytes
          final bytesList = fileData['bytes'];
          final bytes = bytesList is Uint8List ? bytesList : Uint8List.fromList(bytesList as List<int>);
          final filename = fileData['filename'] as String? ?? 'file_${DateTime.now().millisecondsSinceEpoch}';
          final contentTypeStr = fileData['contentType'] as String?;

          if (contentTypeStr != null) {
            multipartFile = http.MultipartFile(
              fieldName,
              Stream.value(bytes),
              bytes.length,
              filename: filename,
              contentType: http.MediaType.parse(contentTypeStr),
            );
          } else {
            multipartFile = http.MultipartFile.fromBytes(
              fieldName,
              bytes,
              filename: filename,
            );
          }
        } else {
          return Failure(ErrorResponse(
              unifiedHttpClientEnum: UnifiedHttpClientEnum.badRequestError,
              errorResponseHolder:
                  ErrorResponseHolder(defaultMessage: 'Invalid file data for field "$fieldName". Must provide either "path" or "bytes".')));
        }

        request.files.add(multipartFile);
      }
    }

    // Send request
    final streamedResponse = _client != null ? await _client!.send(request) : await request.send();

    // Convert streamed response to regular response
    final response = await http.Response.fromStream(streamedResponse);
    await UnifiedInterceptorRunner.runOnResponse(
      UnifiedResponse(
        statusCode: response.statusCode,
        data: response.body,
        headers: response.headers,
        request: prepared,
      ),
      _interceptors,
    );
    return response;
  } on PlatformException catch (e, st) {
    await _notifyError(e, st, request: UnifiedRequest(method: 'POST', uri: url, headers: headers, body: {'files': files, 'fields': fields}));
    return Failure(ErrorResponse(
        unifiedHttpClientEnum: UnifiedHttpClientEnum.platformExceptionError,
        errorResponseHolder: ErrorResponseHolder(defaultMessage: 'Platform Exception Caught')));
  } on SocketException catch (e, st) {
    await _notifyError(e, st, request: UnifiedRequest(method: 'POST', uri: url, headers: headers, body: {'files': files, 'fields': fields}));
    return Failure(ErrorResponse(
        unifiedHttpClientEnum: UnifiedHttpClientEnum.socketExceptionError,
        errorResponseHolder: ErrorResponseHolder(defaultMessage: 'Socket Exception:$e')));
  } on FormatException catch (e, st) {
    await _notifyError(e, st, request: UnifiedRequest(method: 'POST', uri: url, headers: headers, body: {'files': files, 'fields': fields}));
    return Failure(ErrorResponse(
        unifiedHttpClientEnum: UnifiedHttpClientEnum.formatExceptionError,
        errorResponseHolder: ErrorResponseHolder(defaultMessage: 'format exception Error')));
  } catch (e, st) {
    await _notifyError(e, st, request: UnifiedRequest(method: 'POST', uri: url, headers: headers, body: {'files': files, 'fields': fields}));
    return Failure(ErrorResponse(
        unifiedHttpClientEnum: UnifiedHttpClientEnum.undefined,
        errorResponseHolder: ErrorResponseHolder(defaultMessage: 'something went Wrong : $e')));
  }
}