multipartFileUpload method
Future<PixelBinImage?>
multipartFileUpload(
- File file,
- SignedDetails signedDetails,
- int chunkSize,
- int concurrency,
Implementation
Future<PixelBinImage?> multipartFileUpload(File file,
SignedDetails signedDetails, int chunkSize, int concurrency) async {
final fileSize = await file.length();
final chunkSizeInBytes = 1024 * chunkSize;
final semaphore =
Semaphore(concurrency, onEachCompleted: (int milliseconds) {
print('Chunk uploaded in $milliseconds ms');
});
var partNumber = 0;
var offset = 0;
var errorOccurred = false;
var parts = <int>[];
List<Future<void>> uploadFutures = [];
while (offset < fileSize && !errorOccurred) {
final end = (offset + chunkSizeInBytes).clamp(0, fileSize);
final chunk = await readChunk(file, offset, end - offset);
partNumber++;
final url = '${signedDetails.url}&partNumber=$partNumber';
final request = http.MultipartRequest('PUT', Uri.parse(url));
signedDetails.fields.forEach((key, value) {
request.fields[key] = value;
});
request.files
.add(http.MultipartFile.fromBytes('file', chunk, filename: 'chunk'));
final client = http.Client();
uploadFutures.add(semaphore.withPermit(() async {
final response = await client.send(request);
final responseBody = await response.stream.bytesToString();
print("Response: ${response.statusCode} $responseBody");
if (response.statusCode >= 200 && response.statusCode < 300) {
parts.add(partNumber);
} else {
errorOccurred = true;
throw Exception(
"Request Error: ${response.statusCode} $responseBody");
}
}));
offset = end;
}
await Future.wait(uploadFutures);
if (!errorOccurred) {
return completeMultipartUpload(
signedDetails.url, signedDetails.fields, partNumber);
}
throw Exception("Unknown Error occurred");
}