extractFileToDisk function
Future<void>
extractFileToDisk(
- String inputPath,
- String outputPath, {
- String? password,
- int? bufferSize,
- ArchiveCallback? callback,
Implementation
Future<void> extractFileToDisk(String inputPath, String outputPath,
{String? password, int? bufferSize, ArchiveCallback? callback}) async {
Directory? tempDir;
var archivePath = inputPath;
var posixSupported = posix.isPosixSupported();
const String extensionMsg =
'.tar.gz, .tgz, .tar.bz2, .tbz, .tar.xz, .txz, .tar or .zip';
// get the extension of the input file with up to 2 components
// e.g. for file.tar.gz, it will return '.tar.gz'
var archiveExt = getInputExtension(archivePath);
if (archiveExt.isEmpty) {
throw ArgumentError.value(
inputPath,
'inputPath',
'No file extension detected, must end with $extensionMsg',
);
}
if (archiveExt == '.tar.gz' || archiveExt == '.tgz') {
tempDir = Directory.systemTemp.createTempSync('dart_archive');
archivePath = path.join(tempDir.path, 'temp.tar');
final input = InputFileStream(inputPath);
final output = OutputFileStream(archivePath, bufferSize: bufferSize);
GZipDecoder().decodeStream(input, output);
await input.close();
await output.close();
archiveExt = '.tar';
} else if (archiveExt == '.tar.bz2' || archiveExt == '.tbz') {
tempDir = Directory.systemTemp.createTempSync('dart_archive');
archivePath = path.join(tempDir.path, 'temp.tar');
final input = InputFileStream(inputPath);
final output = OutputFileStream(archivePath, bufferSize: bufferSize);
BZip2Decoder().decodeStream(input, output);
await input.close();
await output.close();
archiveExt = '.tar';
} else if (archiveExt == '.tar.xz' || archiveExt == '.txz') {
tempDir = Directory.systemTemp.createTempSync('dart_archive');
archivePath = path.join(tempDir.path, 'temp.tar');
final input = InputFileStream(inputPath);
final output = OutputFileStream(archivePath, bufferSize: bufferSize);
XZDecoder().decodeStream(input, output);
await input.close();
await output.close();
archiveExt = '.tar';
}
InputStream? toClose;
Archive archive;
if (archiveExt == '.tar') {
final input = InputFileStream(archivePath);
archive = TarDecoder().decodeStream(input, callback: callback);
toClose = input;
} else if (archiveExt == '.zip') {
final input = InputFileStream(archivePath);
archive = ZipDecoder()
.decodeStream(input, password: password, callback: callback);
toClose = input;
} else {
throw ArgumentError.value(inputPath, 'inputPath', 'Must end $extensionMsg');
}
for (final file in archive) {
final filePath = path.join(outputPath, path.normalize(file.name));
if (!_isWithinOutputPath(outputPath, filePath)) {
continue;
}
if (file.isSymbolicLink) {
if (!_isValidSymLink(outputPath, file)) {
continue;
}
}
if (file.isDirectory && !file.isSymbolicLink) {
Directory(filePath).createSync(recursive: true);
continue;
}
if (file.isSymbolicLink) {
final link = Link(filePath);
final p = path.normalize(file.symbolicLink ?? "");
link.createSync(p, recursive: true);
} else if (file.isFile) {
final output = OutputFileStream(filePath, bufferSize: bufferSize);
try {
file.writeContent(output);
} catch (_) {}
if (posixSupported) {
posix.chmod(filePath, file.unixPermissions.toRadixString(8));
}
await output.close();
}
}
await toClose.close();
await archive.clear();
if (tempDir != null) {
await tempDir.delete(recursive: true);
}
}