uploadFile static method
Uploads a file to the Encatch server for a specific form question.
Accepts either a local file path (UploadFileRequest.filePath) or base64 content (UploadFileRequest.fileData) forwarded from the WebView form engine. UploadFileRequest.fileData may be raw base64 or a data URL.
Returns the permanent UploadFileResponse.fileUrl on success.
Implementation
static Future<UploadFileResponse> uploadFile(UploadFileRequest params) async {
if (!_initialized) throw StateError('Encatch SDK is not initialized');
final url = Uri.parse('$_apiBaseUrl/${_endpoints['upload']!}');
final headers = _buildHeaders();
late final String name;
late final http.MultipartFile multipartFile;
if (params.filePath != null) {
final file = File(params.filePath!);
name = params.fileName ?? file.uri.pathSegments.last;
multipartFile = await http.MultipartFile.fromPath(
'file',
params.filePath!,
filename: name,
);
} else {
// base64 path — decode and build from bytes
name = params.fileName ?? 'upload';
final Uint8List bytes = base64Decode(
_extractBase64Payload(params.fileData!),
);
multipartFile = http.MultipartFile.fromBytes(
'file',
bytes,
filename: name,
contentType: _uploadMediaType(params.mimeType),
);
}
var lastProgressPercent = -1;
void emitProgress(int percent) {
final clampedPercent = percent.clamp(0, 100).toInt();
if (clampedPercent == lastProgressPercent) return;
lastProgressPercent = clampedPercent;
params.onProgress?.call(clampedPercent);
}
final request =
_ProgressMultipartRequest(
'POST',
url,
onProgress: (bytesSent, totalBytes) {
if (totalBytes <= 0) return;
final percent = ((bytesSent / totalBytes) * 100).floor();
final bucketedPercent = (percent ~/ 5) * 5;
emitProgress(bucketedPercent);
},
)
..headers.addAll(headers)
..fields['formId'] = params.feedbackConfigurationId
..fields['questionId'] = params.questionId
..files.add(multipartFile);
_logger.debug('Uploading file: $name');
final streamedResponse = await _httpClient.send(request);
final response = await http.Response.fromStream(streamedResponse);
if (response.statusCode < 200 || response.statusCode >= 300) {
throw Exception(
'Encatch upload error: status ${response.statusCode} — ${response.body}',
);
}
final decoded = jsonDecode(response.body) as Map<String, dynamic>;
final result = UploadFileResponse.fromJson(decoded);
_logger.debug('Upload complete: ${result.fileUrl}');
emitProgress(100);
return result;
}