uploadFile method

Future<void> uploadFile(
  1. String name, {
  2. required List<int> bytes,
  3. required String filename,
})

Uploads bytes for a file field and applies the outcome.

Success goes through change — a single-file field's value becomes the stored path; a multiple field's value gains it, one append per upload call, because the endpoint serves one file per request and the client loops. Either way any stale error on the field clears the same way any other edit clears one.

Failure routes on UploadFailed.statusCode, the same way submit routes a write's 422 by field name: a 422 is this field's own refusal (too large, wrong type) and lands as its error, value untouched — a failed upload must never clear a file the record already has. Anything else — a bare 403/500, an offline transport, a host that never implemented FilamentUploadTransport — is not a fact about what the user picked, so it reaches formError instead, same as an unmappable write failure.

Implementation

Future<void> uploadFile(
  String name, {
  required List<int> bytes,
  required String filename,
}) async {
  final result = await _source.uploadFile(
    resource.key,
    name,
    bytes: bytes,
    filename: filename,
  );

  // Disposal can land during the await — the user backed out of the form
  // mid-upload. Guarded here, where the asymmetry is: both failure
  // branches already notify through _notify(), but success routes through
  // [change], whose bare notifyListeners() asserts on a disposed
  // ChangeNotifier. change() itself stays unguarded on purpose — its
  // other callers are synchronous taps from a live widget, and a
  // silently-no-op change() would hide a real lifecycle bug there.
  if (_disposed) return;

  switch (result) {
    case UploadSuccess(:final path):
      change(name, _uploadedValue(name, path));
    case UploadFailed(:final message, :final statusCode)
        when statusCode == 422:
      _fieldErrors = Map.unmodifiable({
        ..._fieldErrors,
        name: message ?? strings.uploadFailed,
      });
      _notify();
    case UploadFailed(:final message):
      _formError = (message == null || message.isEmpty)
          ? strings.uploadFailed
          : message;
      _notify();
  }
}