How to get the File Extension from a string Path - flutter

I've got file path saved in variable and I want to get the file type extension by using path package https://pub.dev/packages/path So far I managed to do it by splitting the string like this
final path = "/some/path/to/file/file.dart";
print(path.split(".").last); //prints dart
Is there any way to achieve this with path package?

You can use the extension function in the path package to get the extension from a file path:
import 'package:path/path.dart' as p;
final path = '/some/path/to/file/file.dart';
final extension = p.extension(path); // '.dart'
If your file has multiple extensions, like file.dart.js, you can specify the optional level parameter:
final extension = p.extension('file.dart.js', 2); // '.dart.js'

No need of any extension. You can try below code snippet.
String getFileExtension(String fileName) {
try {
return "." + fileName.split('.').last;
} catch(e){
return null;
}
}

This small function can parse filepath or url and find basename, extension and absolute path. It doesn't check file path exist and not check basename is folder or file.
Map parsePath(String filepath) {
Map p1 = new Map();
int ind1 = filepath.indexOf("://");
if (ind1 > 0) {
p1["fullpath"] = filepath;
} else {
p1["fullpath"] = File(filepath).absolute.path;
}
p1["path"] = filepath;
List<String> v = filepath.split("/");
if (v.length > 1) {
p1["basename"] = v.last;
} else if (filepath.split("\\").length > 1) {
p1["basename"] = filepath.split("\\").last;
} else {
p1["basename"] = v.last;
}
p1["extension"] = p1["basename"].split('.').last;
if (p1["basename"] == p1["extension"]) p1["extension"] = "";
return p1;
}

Related

Dart is replacing "&" with "\u0026" in a URL

I am using flutter to process a link and download it to the device using dio package.
But the problem is dart is replacing all '&' with '\u0026' and making the link unusable. is there a way to avoid this problem? Thanks in advance.
Here's the code:
const uuid = Uuid();
final Dio dio = Dio();
// * create random id for naming downloaded file
final String randid = uuid.v4();
// * create a local instance of state all media
List<MediaModel> allMedia = state.allMedia;
// * create an instance of IGDownloader utility class from ~/lib/utilities
final IGDownloader igd = IGDownloader();
// * make a download link from provided link from the GetNewMedia event
final link = await igd.getPost(event.link);
link.replaceAll('\u0026', '&');
print(await link);
Output:
// expected : "http://www.example.com/example&examples/"
// result: "http://www.example.com/example\u0026example"
Pass your url to cleanContent function and don't forget to add imports
import 'package:html/parser.dart';
import 'package:html_unescape/html_unescape.dart';
static String cleanContent(String content, {bool decodeComponent = false}) {
if (content.contains("<p>")) {
content = content.replaceAll("<p>", "").trim();
}
if (content.contains("</p>")) {
content = content.replaceAll("</p>", "").trim();
}
var unescape = HtmlUnescape();
content = unescape.convert(content).toString();
if (content.contains("\\<.*?\\>")) {
content = content.replaceAll("\\<.*?\\>", "").trim();
}
content = parseHtmlString(content,decodeComponent: decodeComponent);
return content;
}
static String parseHtmlString(String htmlString,{bool decodeComponent = false}) {
final document = parse(htmlString);
String parsedString = parse(document.body!.text).documentElement!.text;
if(parsedString.contains("%3A")){
parsedString = parsedString.replaceAll("%3A", ":");
}
if(parsedString.contains("%2F")){
parsedString = parsedString.replaceAll("%2F", "/");
}
if(decodeComponent){
parsedString = Uri.decodeComponent(parsedString);
}
return parsedString;
}
replaceAll returns the modified string, but leaves original String untouched.
Try:
print(await link.replaceAll('\u0026', '&'));
or
newLink = link.replaceAll('\u0026', '&');
print(await newLink);

How do I make a separate folder for my app and store images there? Flutter

Hey guys so I wish to make a new folder for my app under Android and then store images there which will be retrieved for future use.
Here's what I have tried -
Future<bool> LocalImage(String url) async {
Directory directory;
var dio = Dio();
try {
if (Platform.isAndroid) {
if (await _requestPermission(Permission.storage) &&
// access media location needed for android 10/Q
await _requestPermission(Permission.accessMediaLocation) &&
// manage external storage needed for android 11/R
await _requestPermission(Permission.manageExternalStorage)) {
directory = (await getExternalStorageDirectory()) as Directory;
String newPath = "";
print(directory);
List<String> paths = directory.path.split("/");
for (int x = 1; x < paths.length; x++) {
String folder = paths[x];
if (folder != "Android") {
newPath += "/" + folder;
} else {
break;
}
}
newPath = newPath + "/Verif-ID";
if (await Directory(newPath).exists()){
;
}
else{ directory = Directory(newPath);
}
} else {
return false;
}
} else {
if (await _requestPermission(Permission.photos)) {
directory = await getTemporaryDirectory();
} else {
return false;
}
}
if (await directory.exists()) {
File saveFile = File(directory.path );
await dio.download(url, saveFile.path,);
return true;
}
} catch (e) {
print(e);
}
return false;
}
The issues I am currently facing are-
1.It does make a new folder by that name but no download is happening
2. I keep getting the following in my console
FileSystemException: Cannot create file, path = '/storage/emulated/0/Android/data/com.example.id_me/files' (OS Error: Is a directory, errno = 21)
I understand that this error must mean that a folder of the name already exists but I thought my if conditions were checking that but I guess not. My logics are not the best haha.
This is my first flutter app so I am very sorry if this was a silly doubt.
The URL will be from my firebase database.
Add a file name to a directory path.
savePath: The path to save the downloading file later. A path with String type, eg "xs.jpg"
await dio.download(url, saveFile.path + "/xs.jpg")
See download for details.

Flutter/Dart: Saving an image file to "/storage/emulated/0/Picture/AppFolder/"

using
final dir = await getExternalStorageDirectory();
Image get saved in
/storage/emulated/0/Android/data/com.example.flutter_app/files/
But I want to store it in ../0/Pictures/app_name/ so that it shows up in the gallery.
I looked up all over the www and couldn't figure out. Please advise.
You have to first extract the root Path from the returned location
rootPath = /storage/emulated/0/
than create the Pictures and app_name Directory (to avoid exception when the directory doesn't exist)
then save file in /storage/emulated/0/Pictures/app_name/
here's a simple example to help you understand:
...
Directory externalPath = (await getExternalStorageDirectory());
String picturesDirName = "Pictures";
String appNameDirName = "app_name";
// Splitting the externalPath
List<String> externalPathList = externalPath.path.split('/');
// getting Position of 'Android'
int posOfAndroidDir = externalPathList.indexOf('Android');
//Joining the List<Strings> to generate the rootPath with "/" at the end.
String rootPath = externalPathList.sublist(0, posOfAndroidDir).join('/');
rootPath+="/";
//Creating Pictures Directory (if not exist)
Directory picturesDir = Directory(rootPath+picturesDirName+"/");
if (!picturesDir.existsSync()) {
//Creating Directory
await picturesDir.create(recursive: true);
//Directory Created
} else {
//Directory Already Existed
}
//Creating "app_name" Directory (if not exist)
Directory appNameDir = Directory(rootPath+picturesDirName+"/"+appNameDirName+"/");
if (!appNameDir.existsSync()) {
//Creating Directory
await appNameDir.create(recursive: true);
//Directory Created
} else {
//Directory Already Existed
}
//Creating String varible to store the path where you want to save file.
String fileSaveLocation = rootPath+picturesDirName+"/"+appNameDirName+"/";
// Or you can also use templates like this
String fileSaveLocation2 = "$rootPath$picturesDirName/$appNameDirName/";
//Your File Path where you want to save you file.
String filePath = fileSaveLocation+"text.txt";
// Or you can also use templates like this
String filePath2 = "${fileSaveLocation2}test.txt";
...
You can optimize the above code as per your liking.
hope this is the solution you were looking.
Here, Is how you can acheive this,
final Directory extDir = await getExternalStorageDirectory();
String dirPath = '${extDir.path}/app_name/pictures';
dirPath = dirPath.replaceAll("Android/data/com.example.flutter_app/files/", "");
await Directory(dirPath).create(recursive: true);
// start File Operations Here with dirPath variable
Update:
Along with detailed answer below, I came across a couple of plugins which deals specially with media content.
From Flutter.dev docs:
The plugin currently supports access to two file system locations:
gallery_saver Plugin: See Full Example
GallerySaver.saveImage(path).then((bool success) {// code }
Image_gallery_saver: See Full Example
await ImageGallerySaver.saveImage(Uint8List.fromList(response.data), quality: 60, name: "hello");
Creating the path manually: Source
await Permission.storage.request();
if (await Permission.storage.isGranted) {
var dir = await getExternalStorageDirectory();
Dio dio = Dio();
var newPath = "";
List<String> paths = dir.path.split("/");
for (int x = 1; x < paths.length; x++) {
String folder = paths[x];
if (folder != "Android") {
newPath += "/" + folder;
}
else {
break;
}
}
var picfolder = "/Pictures/";
newPath = newPath + picfolder + AppStrings['AppName'];
Other Useful References:
Android Data Storage
MediaStore in Flutter

How do I add a language formatter which is a terminal command?

We have a language format command mint format src/main.mint which edits the file in place. Is there an appropriate way to register this action as a document formatter such that it can be fired when someone pressed Shift+Option+F?
You can copy the file to a temp directory, modify it with the command line tool, then read and provide it to VSCode
formatter.ts
import vscode = require("vscode");
import cp = require("child_process");
import fs = require("fs");
import { getDirtyFile } from "./utils";
export class MintFormattingProvider
implements vscode.DocumentFormattingEditProvider {
public provideDocumentFormattingEdits(
document: vscode.TextDocument,
options: vscode.FormattingOptions,
token: vscode.CancellationToken
): vscode.TextEdit[] | Thenable<vscode.TextEdit[]> {
return new Promise((resolve, reject) => {
let file = getDirtyFile(document);
let res = cp.spawnSync("mint", ["format", file], {
cwd: vscode.workspace.rootPath,
});
if (res.status !== 0) {
reject(res.error);
} else {
if (!fs.existsSync(file)) {
reject(file + " file not found");
} else {
let content = fs.readFileSync(file, "utf-8");
let range = document.validateRange(
new vscode.Range(
new vscode.Position(0, 0),
new vscode.Position(1000000, 1000000)
)
);
resolve([vscode.TextEdit.replace(range, content)]);
}
}
});
}
}
utils.ts
import fs = require("fs");
import path = require("path");
import os = require("os");
import vscode = require("vscode");
/**
* Returns temporary file path of edited document.
*/
export function getDirtyFile(document: vscode.TextDocument): string {
var dirtyFilePath = path.normalize(
path.join(os.tmpdir(), "vscodemintdirty.mint")
);
fs.writeFileSync(dirtyFilePath, document.getText());
return dirtyFilePath;
}
export function createAndShowOutputWindow(): vscode.OutputChannel {
var channel = vscode.window.createOutputChannel("mint");
channel.show();
return channel;
}

MP3 TagLib search and copy issue

Greetings to all of you.
My problem is:
I need to search through user selected folder that contains MP3 files and check which file(s) has or contains specified tag. If it does, i will copy it to specified folder. I have managed to do something, but only partially, cause for example, i manage to copy genre "Pop" files, but not "Blues" files.
Getting contains to work is a total nightmare, cant get it to work at all.
Code:
try
{
FolderBrowserDialog folder = new FolderBrowserDialog();
DialogResult result = folder.ShowDialog();
string genre = "Blues";
var matchingFiles = Directory.GetFiles(folder.SelectedPath, "*.mp3", SearchOption.AllDirectories).Where(x =>
{
var f = TagLib.File.Create(x);
return (((TagLib.Id3v2.Tag)f.GetTag(TagTypes.Id3v2)).JoinedGenres == genre);
});
foreach (string f in matchingFiles)
{
System.IO.File.Copy(f, Path.Combine(#"destinationFolder", new FileInfo(f).Name));
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
Any help is welcome.
Problem solved:
try
{
FolderBrowserDialog folder = new FolderBrowserDialog();
DialogResult result = folder.ShowDialog();
string upit = search.Text;
var matchingFiles = Directory.GetFiles(folder.SelectedPath, "*.mp3", SearchOption.AllDirectories).Where(x =>
{
var f = TagLib.File.Create(x);
return (((TagLib.Id3v2.Tag)f.GetTag(TagTypes.Id3v2)).Comment != null && ((TagLib.Id3v2.Tag)f.GetTag(TagTypes.Id3v2)).Comment.Contains(upit));
}
);
foreach (string f in matchingFiles)
{
System.IO.File.Copy(f, Path.Combine(path, new FileInfo(f).Name));
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + "\n" + ex.StackTrace);
}