This solution
- Downloads an image from the server.
- Shows downloading progress.
- After download, the image is saved to devise storage.
Code:
import 'package:http/http.dart' as http;
class _MyPageState extends State<MyPage> {
int _total = 0, _received = 0;
late http.StreamedResponse _response;
File? _image;
final List<int> _bytes = [];
Future<void> _downloadImage() async {
_response = await http.Client()
.send(http.Request('GET', Uri.parse('https://upload.wikimedia.org/wikipedia/commons/f/ff/Pizigani_1367_Chart_10MB.jpg')));
_total = _response.contentLength ?? 0;
_response.stream.listen((value) {
setState(() {
_bytes.addAll(value);
_received += value.length;
});
}).onDone(() async {
final file = File('${(await getApplicationDocumentsDirectory()).path}/image.png');
await file.writeAsBytes(_bytes);
setState(() {
_image = file;
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton.extended(
label: Text('${_received ~/ 1024}/${_total ~/ 1024} KB'),
icon: Icon(Icons.file_download),
onPressed: _downloadImage,
),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Center(
child: SizedBox.fromSize(
size: Size(400, 300),
child: _image == null ? Placeholder() : Image.file(_image!, fit: BoxFit.fill),
),
),
),
);
}
}
Upload using Multipart:
import 'dart:convert';
import 'package:http/http.dart' as http;
// ...
final jsonPayload = {'base64File': 'abc123', 'something': 'else'};
// We are using a StreamedRequest so we can track the upload progress
final streamedRequest = http.StreamedRequest("POST", apiUri);
streamedRequest.headers['content-type'] = 'application/json';
// Length transferred (to calculate upload progress)
var transferredLength = 0;
// Upload progress (from 0.0 to 1.0)
var uploadProgress = 0.0;
// The stringified JSON payload
var stringEncodedPayload = jsonEncode(jsonPayload);
// Total length (to calculate upload progress)
var totalLength = stringEncodedPayload.length;
// Create a stream of the payload string
Stream.value(stringEncodedPayload)
// Transform the string-stream to a byte stream (List<int>)
.transform(utf8.encoder)
// Start reading the stream in chunks, submitting them to the streamedRequest for upload
.listen((chunk) {
transferredLength += chunk.length;
uploadProgress = transferredLength / totalLength;
print("Chunk: ${chunk.length}, transferred: $transferredLength, progress: $uploadProgress");
streamedRequest.sink.add(chunk);
}, onDone: () {
print("Done. Total: $totalLength, transferred: $transferredLength, progress: $uploadProgress");
streamedRequest.sink.close();
});
final result = await client.send(streamedRequest).then(http.Response.fromStream);
print("----------->");
print(result.statusCode);
print(result.body);
print("<-----------");
The output:
flutter: Chunk: 1024, transferred: 1024, progress: 0.0008807503580198599
flutter: Chunk: 1024, transferred: 2048, progress: 0.0017615007160397197
flutter: Chunk: 1024, transferred: 3072, progress: 0.0026422510740595796
...
flutter: Chunk: 1024, transferred: 1159168, progress: 0.9970094052784814
flutter: Chunk: 1024, transferred: 1160192, progress: 0.9978901556365013
flutter: Chunk: 1024, transferred: 1161216, progress: 0.9987709059945211
flutter: Chunk: 1024, transferred: 1162240, progress: 0.9996516563525409
flutter: Chunk: 405, transferred: 1162645, progress: 1.0
flutter: Done. Total: 1162645, transferred: 1162645, progress: 1.0