Files
Kalulu/folder_unzipper.gd

91 lines
2.8 KiB
GDScript

class_name FolderUnzipper
extends ZIPReader
signal file_count(count: int)
signal file_copied(count: int, name: String)
signal finished()
func _is_directory_path(path: String) -> bool:
return path.ends_with("/")
func extract(zip_path: String, extract_path: String, extract_in_subfolder: bool = true) -> String:
Log.trace("FolderUnzipper: Extracting %s to %s" % [zip_path, extract_path])
var err: Error = open(zip_path)
if err != OK:
Log.error("FolderUnzipper: Error %s while opening %s" % [error_string(err), zip_path])
close()
file_count.emit(0)
finished.emit()
return ""
var extract_folder: String = extract_path
if extract_in_subfolder:
extract_folder = extract_path.path_join(zip_path.get_file().get_basename())
var all_files: PackedStringArray = get_files()
var total_files: int = 0
for sub_path: String in all_files:
if not _is_directory_path(sub_path):
total_files += 1
file_count.emit(total_files)
Log.trace("FolderUnzipper: %d files found" % total_files)
var copied_file: int = 0
var progress_step: int = 25 if OS.has_feature("web") else 1
var first_folder: String = ""
var last_sub_path: String = ""
for sub_path: String in all_files:
last_sub_path = sub_path
if _is_directory_path(sub_path):
first_folder = sub_path.trim_suffix("/")
break
if not first_folder and last_sub_path != "":
first_folder = last_sub_path.split("/")[0]
for sub_path: String in all_files:
if _is_directory_path(sub_path):
continue
var file_name: String = extract_folder.path_join(sub_path)
file_name = Utils.get_safe_file_path(file_name)
var folder_name: String = file_name.get_base_dir()
if not DirAccess.dir_exists_absolute(folder_name):
var mkdir_err: Error = DirAccess.make_dir_recursive_absolute(folder_name)
if mkdir_err != OK:
Log.error("FolderUnzipper: Cannot create directory %s. Error: %s" % [folder_name, error_string(mkdir_err)])
continue
var file: FileAccess = FileAccess.open(file_name, FileAccess.WRITE)
var error: Error = FileAccess.get_open_error()
if error != OK or file == null:
Log.error("FolderUnzipper: Extract: Cannot open file %s. Error: %s" % [file_name, error_string(error)])
continue
var data: PackedByteArray = read_file(sub_path)
if data.is_empty():
# Zero-byte files can be valid files, so we warn but do not skip them.
Log.warn("FolderUnzipper: Empty data for %s" % sub_path)
if typeof(data) != TYPE_PACKED_BYTE_ARRAY:
Log.warn("FolderUnzipper: Invalid data for %s" % sub_path)
file.close()
continue
file.store_buffer(data)
file.close()
copied_file += 1
if copied_file % progress_step == 0 or copied_file == total_files:
Log.trace("FolderUnzipper: Copied %s" % file_name)
file_copied.emit(copied_file, file_name)
close()
finished.emit()
Log.trace("FolderUnzipper: Extraction finished in %s" % extract_folder)
return first_folder