Files
2026-05-27 19:19:11 +08:00

250 lines
6.1 KiB
Dart

class FileUtils {
static String safeDecodePathSegment(String value, {int maxPasses = 5}) {
var decoded = value;
for (var i = 0; i < maxPasses; i++) {
try {
final next = Uri.decodeComponent(decoded);
if (next == decoded) break;
decoded = next;
} on FormatException {
break;
} on ArgumentError {
break;
}
}
return decoded;
}
static String decodePathForDisplay(String path) {
return path
.split('/')
.map((segment) => safeDecodePathSegment(segment))
.join('/');
}
static String toCloudreveUri(String path) {
if (path.startsWith('cloudreve://')) return path;
if (path == '/' || path.isEmpty) return 'cloudreve://my';
final cleanPath = path.startsWith('/') ? path.substring(1) : path;
return 'cloudreve://my/$cleanPath';
}
static String toCloudreveUriWithQuery(
String path,
Map<String, String> queryParameters,
) {
final uri = Uri.parse(toCloudreveUri(path));
return uri.replace(queryParameters: queryParameters).toString();
}
static String getFileExtension(String fileName) {
final dotIndex = fileName.lastIndexOf('.');
if (dotIndex == -1) return '';
return fileName.substring(dotIndex + 1).toLowerCase();
}
static bool isImageFile(String fileName) {
const imageExtensions = [
'jpg',
'jpeg',
'png',
'gif',
'webp',
'bmp',
'svg',
'heic',
'heif',
'avif',
'tif',
'tiff',
];
return imageExtensions.contains(getFileExtension(fileName));
}
static bool isFlutterRenderableImageFile(String fileName) {
const renderableImageExtensions = [
'jpg',
'jpeg',
'png',
'gif',
'webp',
'bmp',
];
return renderableImageExtensions.contains(getFileExtension(fileName));
}
static bool isVideoFile(String fileName) {
const videoExtensions = [
'mp4',
'webm',
'mkv',
'avi',
'mov',
'flv',
'wmv',
'm4v',
'mpg',
'mpeg',
'3gp',
'ts',
'm2ts',
];
return videoExtensions.contains(getFileExtension(fileName));
}
static bool isAudioFile(String fileName) {
const audioExtensions = ['mp3', 'wav', 'ogg', 'flac', 'aac', 'm4a'];
return audioExtensions.contains(getFileExtension(fileName));
}
static bool isPsdFile(String fileName) {
const psdExtensions = ['psd', 'psb'];
return psdExtensions.contains(getFileExtension(fileName));
}
static bool isThumbnailableFile(String fileName) {
final ext = getFileExtension(fileName);
if (ext.isEmpty || ext == 'svg') return false;
return isImageFile(fileName) || isVideoFile(fileName) || isPsdFile(fileName);
}
static bool isPdfFile(String fileName) {
return getFileExtension(fileName) == 'pdf';
}
static bool isTextFile(String fileName) {
const textExtensions = [
'txt',
'md',
'json',
'xml',
'yaml',
'yml',
'ini',
'conf',
];
return textExtensions.contains(getFileExtension(fileName));
}
static bool isCodeFile(String fileName) {
const codeExtensions = [
'js',
'ts',
'tsx',
'jsx',
'dart',
'java',
'py',
'c',
'cpp',
'h',
'hpp',
'cs',
'php',
'rb',
'go',
'rs',
'swift',
'kt',
'html',
'css',
'scss',
'less',
'sql',
'sh',
'bat',
];
return codeExtensions.contains(getFileExtension(fileName));
}
static bool isArchiveFile(String fileName) {
const archiveExtensions = ['zip', 'rar', '7z', 'tar', 'gz', 'bz2'];
return archiveExtensions.contains(getFileExtension(fileName));
}
static bool isDocumentFile(String fileName) {
const docExtensions = [
'doc',
'docx',
'xls',
'xlsx',
'ppt',
'pptx',
'odt',
'ods',
'odp',
];
return docExtensions.contains(getFileExtension(fileName));
}
static bool isPreviewable(String fileName) {
return isImageFile(fileName) ||
isVideoFile(fileName) ||
isPdfFile(fileName) ||
isTextFile(fileName) ||
isCodeFile(fileName);
}
static String getMimeType(String fileName) {
final ext = getFileExtension(fileName);
final mimeTypes = {
'jpg': 'image/jpeg',
'jpeg': 'image/jpeg',
'png': 'image/png',
'gif': 'image/gif',
'webp': 'image/webp',
'svg': 'image/svg+xml',
'bmp': 'image/bmp',
'heic': 'image/heic',
'heif': 'image/heif',
'avif': 'image/avif',
'tif': 'image/tiff',
'tiff': 'image/tiff',
'psd': 'image/vnd.adobe.photoshop',
'psb': 'image/vnd.adobe.photoshop',
'mp4': 'video/mp4',
'webm': 'video/webm',
'mkv': 'video/x-matroska',
'avi': 'video/x-msvideo',
'mov': 'video/quicktime',
'flv': 'video/x-flv',
'wmv': 'video/x-ms-wmv',
'm4v': 'video/x-m4v',
'mpg': 'video/mpeg',
'mpeg': 'video/mpeg',
'3gp': 'video/3gpp',
'ts': 'video/mp2t',
'm2ts': 'video/mp2t',
'mp3': 'audio/mpeg',
'wav': 'audio/wav',
'ogg': 'audio/ogg',
'flac': 'audio/flac',
'aac': 'audio/aac',
'm4a': 'audio/mp4',
'pdf': 'application/pdf',
'txt': 'text/plain',
'json': 'application/json',
'xml': 'application/xml',
'html': 'text/html',
'css': 'text/css',
'js': 'application/javascript',
};
return mimeTypes[ext] ?? 'application/octet-stream';
}
static String getFileIcon(String fileName) {
if (isImageFile(fileName)) return 'assets/icons/image.svg';
if (isVideoFile(fileName)) return 'assets/icons/video.svg';
if (isAudioFile(fileName)) return 'assets/icons/audio.svg';
if (isPdfFile(fileName)) return 'assets/icons/pdf.svg';
if (isTextFile(fileName)) return 'assets/icons/text.svg';
if (isCodeFile(fileName)) return 'assets/icons/code.svg';
if (isArchiveFile(fileName)) return 'assets/icons/archive.svg';
if (isDocumentFile(fileName)) return 'assets/icons/document.svg';
return 'assets/icons/file.svg';
}
}