resume downloading messes up the file - flutter

i'm trying to download a large file and be able to resume the downloading where it left off,
i'm currently using this code to achieve this
//downloadUntil is a large number (~10GB) so that if we don't specify
//our own number the http will automatically trim it to the file size.
downloadFile(String url, {int downloadFrom=0, int downloadUntil=99999999999 }) async {
var httpClient = http.Client();
var request = new http.Request('GET', Uri.parse(url));
//we will add Range to the header, downloadFrom will be zero
//if the file is being downloaded for the first time,
//and it will be a different number if we're resuming the download.
request.headers.addAll({'Range': 'bytes=$downloadFrom-$downloadUntil'});
var response = httpClient.send(request);
//create a RandomAccessFile object so that we can write the chunks to the file.
RandomAccessFile raf = await File(downloadPath).open(mode: FileMode.write);
//this variable will keep track of the downloaded bytes,
//we use it to offset the file when writing to it.
int downloaded = downloadFrom;
response.asStream().listen((http.StreamedResponse r) {
r.stream.listen((List<int> chunk) async {
//print the percentage
debugPrint('downloadPercentage: ${downloaded / r.contentLength * 100}');
//offsetting the file
raf.setPositionSync(downloaded);
//then write the downloaded chunk to the file
raf.writeFromSync(chunk);
//update the downloaded variable
downloaded += chunk.length;
}, onDone: () async {
debugPrint('download completed');
return;
});
});
}
the file works fine when for example i have a 150MB video file and download only 50MB by executing this code:-
downloadFile("https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4", downloadUntil: 50000000//~50MB);
the video file works fine, i can watch the downloaded part, everything works as intended.
then i execute this code to download the remaining bytes:-
downloadFile("https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4", downloadFrom: 50000000//~50MB);
then the video file doesn't work anymore, it gets unseekable stream,
i also tried to download the file by downloadFrom:49999900 and replace some of the downloaded bytes to avoid skipping any bytes,
also tried downloadFrom: 50000001 to avoid replacing any downloaded bytes, none of them worked.
what am i doing wrong here?

You are opening the file with FileMode.write which overwrites all the existing bytes saved by the previous download. Change it to FileMode.append and you are good to go.

Related

Flutter - cannot download audio files

It's been 3 days that I try to fix an issue with the download of audio files with my Flutter application. When I try to download audio files, the request keep the "pending" status and finish with no error.
I have research a lot and find something about the contentLength of the client who is always at 0 but it doesn't help.
Now I have tried to make a get request to a website with sample audio files and it doesn't work too. I have tested via Postman and it always work.
My function:
Future<void> _download(String url, String filepath) async {
final response = await this.get("https://file-examples-com.github.io/uploads/2017/11/file_example_MP3_700KB.mp3");// await this.get("$baseURL$url");
log("Try to get audio files: ${response.isOk}");
if (response.isOk) {
File file = File(filepath);
final raf = file.openSync(mode: FileMode.write);
response.bodyBytes.listen((value) {
raf.writeFromSync(value);
}, onDone: () {
log("closed $filepath");
raf.closeSync();
});
}
}
The response.isOk is always false.
I used GetConnect from GetX package who used httpClient.
Via Dart devtools I obtain this from the request:
https://prnt.sc/1q3w33z
https://prnt.sc/1q3x9ot
So I used another package: Dio and now it works.

want to fetch bytes of selected file from device

So basically i want to select the files from my device and encrypt them with the help of bytes.
I am done with the selection part and have done that using file picker if anyone can help me how to get bytes of the file i have selected it would be really helpful.
here is my code to pick files from device
void selectFileFromDevice(d) async{
FilePickerResult filePickerResult = await FilePicker.platform.pickFiles(allowMultiple: true);
if(filePickerResult!=null){
List<io.File> files = filePickerResult.paths.map((path) => io.File(path)).toList();
}else{
print('user cancelled the picker');
}
}
the above code is working absolutely fine i just want to know how can get the bytes of my selected files.
Thank you
you can use the following code to get the bytes of your file
Uint8List bytes = await files[0].readAsBytes();

Blank screen randomly rendered when opening html file in app on iOS after closing app

I have an app that displays html files that are being opened in email client. I am using MethodChannel to send send data from MainActivity/AppDelegate to main.dart, save the file to storage and open in it webview. My main.dart is here https://github.com/akravets/sandbox/blob/master/main.dart.
The html files are quite big - 20 to 30 MB. As I open attachments, everything is ok, but after I close my app and try to open an attachment, I get a blank screen. I can open another file after that, but that first open after closing app always fails.
Relevant code could be here:
String fileName = data.substring(0, indexOfSeparator);
String content = data.substring(indexOfSeparator + 3);
if (_fileName != fileName) {
setState(() {
_fileName = fileName;
writeLog("Setting fileName in state: $fileName");
});
}
final file = await _localFile(fileName);
writeData(file, content).then((f) {
writeLog("File write OK, reloading webView with file ${file.path}");
flutterWebviewPlugin.reloadUrl('file://${file.path}');
}
Any ideas what could be the issue here?
The issue here was that I was setting state and calling flutterWebviewPlugin.reloadUrl('file://${file.path}'); after that. What I suspect was happening is that state would change, build would be called, but reloading of webView would not happen correctly - there was timing issue. What solved the problem was changing state in webView's listener, so that build would be triggered after all the data was ready
flutterWebviewPlugin.onUrlChanged.listen((String url) {
setState(() {
_fileName = fileName;
writeLog("Setting fileName in state: $fileName");
});
});

How to fix Flutter stream exiting whenever i try to listen to it

In a flutter app, I'm trying to read a large csv file one line at a time by opening a stream on it. The issue is that when i try to listen to the stream the execution just skips over that code block and the program ends.
The file I'm opening is located in my assets folder and I've confirmed programmatically that it does exist before opening the stream. Changing the file the stream is opened on doesn't help, the same problem persists. I've also tried to change the way i listen to the stream, following different methods provided by Darts official documentation (that code is commented out) but the outcome is again the same. The assets have been declared in the pubspec.yaml. When i change the code to read the file as a String the program works perfectly but I want to use a stream because the file is so massive that creating a String object for it would take a large amount of time and memory.
void trainDigitsStream() async{
List<List<List>> filters = createRandomFilter(4, 4, 1, -1, 1);
List flattened= new List<double>();
File file = new File("assets/digit_train_data.csv");
if(file.existsSync())print("EXISTS!");
Stream<List<int>> stream = file.openRead();
Stream lines = utf8.decoder.bind(stream).transform(LineSplitter());
/*
try{
await for (var line in lines){
print(line);
}
print("file ended");
}catch(e){
print(e);
}
*/
lines.listen((data){//code exits here, execution never reaches next line
String line = data.toString();
List<List> instance = new List<List<int>>();
List x = new List<int>();
int i = 0;
line.split(',').forEach((d){
x.add(int.parse(d));
i++;
if(i == 28){
instance.add(x);
x = new List<int>();
i = 0;
}
});
List<List<List>> kernels = new List<List<List<double>>>();
List<List> pools = new List<List>();
filters.forEach((f){kernels.add(convo.applyFilter(instance, f, 0));});
kernels.forEach((k){pools.add(pool.maxPool(k, 2));});
pools.forEach((p){flattened.addAll(p);});
});
}
It's hard without further information, It would be better if you can post more information.
So I guess the problem should be , please check the following two steps.
1. Register the assets folder in pubspec.yaml
flutter:
assets:
- assets/digit_train_data.csv
2. You need to use rootBundle to access this csv file, reference document https://flutter.dev/docs/development/ui/assets-and-images
import 'dart:async' show Future;
import 'package:flutter/services.dart' show rootBundle;
Future<String> loadAsset() async {
return await rootBundle.loadString('assets/digit_train_data.csv');
}
similar question here Flutter - Read text file from assets

IONIC3 - WriteFile & WriteExistingFile is unable to overwrite the file

I would like to do image annotation for my Ionic Application. So the flow of the app would be using the camera plugin to take a picture and use FabricJs to draw on the image then save the file.
I hit the roadblock when I am trying to save or overwrite the file. Apparently the source "http://localhost:8080/file/data/user/0/***/files/1547183479807.png" file does not update.
The flow of the app
1) Take picture with #ionic-native/camera
2) Copy the file to a local directory
3) Use this.win.Ionic.WebView.convertFileSrc to convert the file name to "http://localhost:8080/file/data/user/0/***/files/1547183479807.png"
4) Push to another page to access the canvas
5) Use the link to setBackground to my canvas (FabricJs)
6) Draw on the image (Manually)
7) Save the file via overwriting the existing file but nothing works from here on.
I tried to
- overwrite with writeFile & writeExisitingFile, did not work.
- removeFile and writeFile and did not work.
- tried converting to ArrayBuffer rather than Blob and did not work
- tried creating another new file, did not work too (it seems like after I push to a new page, all the file functions does not affect the files)
- tried using native cordova but did not work too.
- delete that same files twice, (first time I did not get an error but the second time I got an error saying "File Does not exist" but when I view the source, the file is also there and appearing in my thumbnail on my App.
private copyFileToLocalDir(namePath, currentName, newFileName,id,index) {
this.file.copyFile(namePath, currentName, this.file.dataDirectory, newFileName).then(success => {
const keys = id.split('-');
let filename = this.file.dataDirectory + newFileName;
this.fp = this.win.Ionic.WebView.convertFileSrc(filename) ;
this.navCtrl.push(AnnotationsPage, {
filepath: this.fp,
filename: newFileName
});
this.presentToast("Image Successfully Added",'middle');
}, error => {
this.presentToast('Error while storing file.','middle');
});
}
Annotation.ts
savePicture() {
let image = this.canvas.toDataURL({
format: 'png'
});
this.saveBase64(image);
}
public saveBase64(base64:string):Promise<string>{
return new Promise((resolve, reject)=>{
var realData = base64.split(",")[1]
let blob=this.b64toBlob(realData,"image/png")
this.file.writeFile(this.file.dataDirectory,this.filename,blob,{replace:true})
// this.file.writeExistingFile(this.file.dataDirectory,this.filename, blob)
.then((val)=>{
console.log('Write Info',val)
let fp = this.win.Ionic.WebView.convertFileSrc(this.file.dataDirectory+this.filename) ;
})
.catch((err)=>{
console.log('error writing blob')
console.log(err);
// reject(err)
})
})
}
b64toBlob(b64Data, contentType) {
contentType = contentType || '';
var sliceSize = 512;
var byteCharacters = atob(b64Data);
var byteArrays = [];
for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
var slice = byteCharacters.slice(offset, offset + sliceSize);
var byteNumbers = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
I check the base64 file, it is working fine (Throw the data to an online converter and it display the picture.
After the function "copyFileToLocalDir", it seems like I am unable to modify the files store in the local directory.
Thanks in advance. Feel free to ask me more question. 7 hours and no result.
Update on the testing, I am doing.
Did File.readAsDataUrl and as expected the file file:///data/user/0/*/files/1547231914843.png updated from the old image to the new edited. (Tested the base64 on some online converter) but it still does not reflect on the source http://localhost:8080/file/data/user/0/***/files/1547231914843.png
Thanks to all those who read through.
After tons of testing, I found out that Ionic Webview's files, will not be updated unless you recall them again (Kind of like a cache and apparently there is no way to reset or flush the cache).
So in my case, I would need to remove the image from the webview and call it out again then it will go back to retrieve again or create another file with another file name and display it.