How to get a list of all cached audio? - flutter

For example, my podcast app has a list of all downloaded podcast, how do I get a list of all LockCachingAudioSource that has been downloaded using request() method?

When you create your LockCachingAudioSource instances, you can choose the location where you want them to be saved. If you create a directory for that purpose, you can obtain a directory listing using Dart's file I/O API. The directory listing will also show partially downloaded files and other temporary files, which you want to ignore. These have extensions .mime and .part.
Having explained that, here is a solution. First, create your cache directory during app init:
final cacheDir = File('/your/choice/of/location');
...
await cacheDir.create(recursive: true);
Then for each audio source, create it like this:
import 'package:path/path.dart' as p;
...
source = LockCachingAudioSource(
uri,
cacheFile: File(p.joinAll([cacheDir, 'yourChoiceOfName.mp3'],
);
Now you can get a list of downloaded files at any time by listing the cacheDir and ignoring any temporary files:
final downloadedFiles = (await _getCacheDir()).list().where((f) =>
!['mime', 'part'].contains(f.path.replaceAll(RegExp(r'^.*\.'), '')));
If you need to turn these files back into the original URI, you could either create your own database to store which file is for which URI, or you choose the file name of each of your cache files by encoding the URI in base64 or something that's reversable, so given a file name, you can then decode it back into the original URI.

Related

camera_windows save picture to different directory

I am using the flutter package camera_windows using the exact sample code listed here
camera_windows
It looks like by default it saves it to the "Pictures" directory in windows but I was wondering how do I save it to a different directory with a different filename also it looks like I cant pass a "path" to the call of the function for example
final XFile file = await CameraPlatform.instance.takePicture(_cameraId);
_showInSnackBar('Picture captured to: ${file.path}');

how to get a list of files from a given path of directory in string in flutter web?

I have a string of path like this:
"C:\xxxx\xxx\xxxx"
how can I get the list of files from this path?
Eventually, I want to load all the files.
If your result is a website, you cannot. No technology can do that, it's a limitation of websites in general, they can only read what you specifically select in your browser. It would be a security nightmare if any website could just go browsing your local disk.
If you need to do that, the user would have to select/upload multiple files themselves or if you really, really need that, you may want to consider a native app, in this case probably flutter-desktop.
As said by #nvoigt a website cannot access the user's computer without requesting the user.
Assuming the directory is part of the project's assets i.e. the folder is deployed with your website, you can read the list of files from the AssetManifest.json.
import 'dart:convert';
import 'package:flutter/services.dart';
final manifestContent = await rootBundle.loadString('AssetManifest.json');
final Map<String, dynamic> manifestMap = json.decode(manifestContent);
List filePaths = manifestMap.keys
.where((String key) => key.contains('mydir/')).toList()

How to delete all the boxes in Hive Flutter?

I am developing an application using Flutter; it will store some data locally, so I decided to use Hive package which was really amazing package to store data. So now I will store all the data locally when the user press the sync button. After that, if the user clicks sync again, I have to delete all the boxes and store data which may or may not have the same box name.
I don't want to increase the application storage to increase if the sync button is clicked, I want to delete all the boxes and again I want to create the box.
You can use deleteFromDisk method. It removes the file which contains the box and closes the box.
_myCourseBox.deleteFromDisk();
Unfortunately, I don't think a feature to clear() all (opened, plus unopened) Hive boxes has been implemented. The box files are basically thrown into your device's application document directory as *.hive files (with compacted files as *.hivec and lock files as *.lock). There's no separate key-value store (or Hive box) that keeps track of previously created boxes, though you can implement such a Hive box yourself and iterate over those values as you please.
In your case, where you simply want to delete all the boxes in one sweep, a workaround could be to place all Hive boxes into a sub-directory (using Hive.initFlutter('chosenPath') ) and simply delete the directory when necessary using standard file operations. The only gotcha being that you call Hive.close() to close all open boxes before attempting this (to delete the undeletable *.lock files).
To simplify cross-platform references to the app's document directory you can use the path_provider package. Add path_provider: ^1.6.5 to your dependencies in pubspec.yaml, and where necessary in your dart application import 'package:path_provider/path_provider.dart'; and import 'dart:io'; for file operations;
Let's say you use Hive.initFlutter('chosenPath') to initialise and store your Hive.
So whenever you want to clear all boxes (after ensuring Hive.close() has been called), you could use the following code:
// Get the application's document directory
var appDir = await getApplicationDocumentsDirectory();
// Get the chosen sub-directory for Hive files
var hiveDb = Directory('${appDir.path}/chosenPath');
// Delete the Hive directory and all its files
hiveDb.delete(recursive: true);
The directory will be re-generated from scratch the next time you call Hive.initFlutter('chosenPath').
You didn't share any code so I will just give an example.
I would suggest you to open the boxes in your main function
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Hive.initFlutter();
Hive.registerAdapter(yourAdapter());
await Hive.openBox('yourBoxName');
}
When user wants to sync, you can do following;
// It will delete all the entry in the box
Hive.box('yourBoxName').clear();
yourSyncOperation();

Uploading file to storage without extension

I am trying to create an app where users can upload files to the "wall". The idea is not important. Each file is added both to storage and to database as [fileName : url) under user's profile. Because of limitations regarding strings in database, I keep filenames without extensions (can't use dot symbol). Uploading works fine but I have a problem with deletion. Based on the file user picks to delete in app I get the filename(without extension). My delete function should delete the file from storage but it cannot locate file because of missing extension.
I use this function to upload the data:
let uploadTask = ref.putData(contents as Data, metadata: myMetadata, completion: { (metadata, error) in ...}
and the file itself:
let contents = try Data(contentsOf: url.standardizedFileURL)
Is it possible to upload "contents" without the extension? Or maybe is there another approach I'm missing?
Thanks for tips.
It's not a really good idea to store the names of random things (including files) as keys in Realtime Database. You could make this easier on yourself by pushing an object at a location in the database for each file uploaded. The pushed object could contain the name and location of the file in Storage, along with any other metadata about that file, and you won't have to mangle that data as long as it's stored in values rather than keys.

Upload same name files to google cloud storage then download them with original names

So in google-cloud-storage if you upload more than one file with the same name to it the last will overwrite what was uploaded before it.
If I want to upload more than one file with the same name I should append some unique thing to the file name e.g. timestamp, random UUID.
But by doing so I'll lose the original file name while downloading, because I want to serve the file directly from google.
If we used the unique identifier as a folder instead of appending it to the file name, e.g. UUID +"/"+ fileName then we can download the file with its original name.
You could turn on Object Versioning which will keep the old versions of the object around.
Alternatively, you can set the Content Disposition header when uploading the object, which should preserve whatever filename you want on download.
instead of using object versioning, you can attach the UUID (or any other unique identifier) and then update the metadata of the object (specifically the content disposition), the following is a part of a python script i've used to remove the forward slashes - added by google cloud buckets when to represent directories - from multiple objects, it's based on this blog post, please keep in mind the double quotes around the content position "file name"
def update_blob_download_name(bucket_name):
""" update the download name of blobs and remove
the path.
:returns: None
:rtype: None
"""
# Storage client, not added to the code for brevity
client = initialize_google_storage_client()
bucket = client.bucket(bucket_name)
for blob in bucket.list_blobs():
if "/" in blob.name:
remove_path = blob.name[blob.name.rfind("/") + 1:] # rfind gives that last occurence of the char
ext = pathlib.Path(remove_path).suffix
remove_id = remove_path[:remove_path.rfind("_id_")]
new_name = remove_id + ext
blob.content_disposition = f'attachment; filename="{new_name}"'
blob.patch()