chunkedUpload method

  1. @override
Future<Response> chunkedUpload({
  1. required String path,
  2. required Map<String, dynamic> params,
  3. required String paramName,
  4. required String idParamName,
  5. required Map<String, String> headers,
  6. dynamic onProgress(
    1. UploadProgress
    )?,
})
override

Upload a file in chunks.

Implementation

@override
Future<Response> chunkedUpload({
  required String path,
  required Map<String, dynamic> params,
  required String paramName,
  required String idParamName,
  required Map<String, String> headers,
  Function(UploadProgress)? onProgress,
}) async {
  InputFile file = params[paramName];
  if (file.path == null && file.bytes == null) {
    throw AppwriteException("File path or bytes must be provided");
  }

  int size = 0;
  if (file.bytes != null) {
    size = file.bytes!.length;
  }

  File? iofile;

  if (file.path != null) {
    iofile = File(file.path!);
    size = await iofile.length();
  }

  late Response res;
  if (size <= CHUNK_SIZE) {
    if (file.path != null) {
      params[paramName] = await http.MultipartFile.fromPath(
          paramName, file.path!,
          filename: file.filename);
    } else {
      params[paramName] = http.MultipartFile.fromBytes(paramName, file.bytes!,
          filename: file.filename);
    }
    return call(
      HttpMethod.post,
      path: path,
      params: params,
      headers: headers,
    );
  }

  var offset = 0;
  if (idParamName.isNotEmpty && params[idParamName] != 'unique()') {
    //make a request to check if a file already exists
    try {
      res = await call(
        HttpMethod.get,
        path: path + '/' + params[idParamName],
        headers: headers,
      );
      final int chunksUploaded = res.data['chunksUploaded'] as int;
      offset = min(size, chunksUploaded * CHUNK_SIZE);
    } on AppwriteException catch (_) {}
  }

  RandomAccessFile? raf;
  // read chunk and upload each chunk
  if (iofile != null) {
    raf = await iofile.open(mode: FileMode.read);
  }

  while (offset < size) {
    List<int> chunk = [];
    if (file.bytes != null) {
      final end = min(offset + CHUNK_SIZE - 1, size - 1);
      chunk = file.bytes!.getRange(offset, end).toList();
    } else {
      raf!.setPositionSync(offset);
      chunk = raf.readSync(CHUNK_SIZE);
    }
    params[paramName] = http.MultipartFile.fromBytes(paramName, chunk,
        filename: file.filename);
    headers['content-range'] =
        'bytes $offset-${min<int>(((offset + CHUNK_SIZE) - 1), size)}/$size';
    res = await call(HttpMethod.post,
        path: path, headers: headers, params: params);
    offset += CHUNK_SIZE;
    if (offset < size) {
      headers['x-appwrite-id'] = res.data['\$id'];
    }
    final progress = UploadProgress(
      $id: res.data['\$id'] ?? '',
      progress: min(offset - 1, size) / size * 100,
      sizeUploaded: min(offset - 1, size),
      chunksTotal: res.data['chunksTotal'] ?? 0,
      chunksUploaded: res.data['chunksUploaded'] ?? 0,
    );
    onProgress?.call(progress);
  }
  raf?.close();
  return res;
}