iOS запись сжатых NSData в файл создает поврежденный zip-файл - PullRequest
1 голос
/ 20 января 2020

Я пытаюсь добиться очень простой вещи в моем приложении iOS: заархивировать файл в папку Documents. Я написал следующее расширение FileManager:

extension FileManager {


    func zipFile(url: URL, deleteOriginal: Bool = false) {
        guard let fileData = try? Data(contentsOf: url) else { return }
        let nsdata = fileData as NSData
        let zipped: NSData
        zipped = (try? nsdata.compressed(using: .zlib)) ?? nsdata
        let zip = zipped as Data
        let zipUrl = url.deletingPathExtension().appendingPathExtension("zip")
        try? FileManager.default.removeItem(at: zipUrl)
        try? zip.write(to: zipUrl)
        if deleteOriginal {
            try? FileManager.default.removeItem(at: url)
        }
    }

}

Однако созданный файл, похоже, поврежден.

I go to Xcode -> Окно -> Устройства и симуляторы , выберите мое устройство, затем мое приложение в списке под ним, нажмите кнопку переключения передач под списком и затем нажмите Скачать контейнер ... чтобы посмотреть файлы. Затем я открываю содержимое загруженного пакета и проверяю папку «Документы» - в ней есть созданный zip-файл. Тем не менее, я не могу открыть его. По умолчанию Ma c создает файл с расширением zip.cpgz, что обычно происходит при повреждении файла. Другие приложения извлечения показывают сообщение об ошибке, говорящее, что файл поврежден. Когда я пытаюсь открыть его в терминале, используя unzip, я вижу следующее сообщение:

iMac:Downloads user$ unzip myzip.zip
Archive:  myzip.zip
  End-of-central-directory signature not found.  Either this file is not
  a zipfile, or it constitutes one disk of a multi-part archive.  In the
  latter case the central directory and zipfile comment will be found on
  the last disk(s) of this archive.
unzip:  cannot find zipfile directory in one of myzip.zip or
        myzip.zip.zip, and cannot find myzip.zip.ZIP, period.

Я пытался не только NSData.compressed, но также и библиотеку с именем DataCompression , и Также реализовано сжатие "себя" с помощью инструкций Apple от здесь . Во всех случаях файл был поврежден одинаково.

Я также пытался отлаживать свой код, отображал сжатый объект Data в отладчике и экспортировал его как файл. Снова поврежден с теми же симптомами.

Есть ли что-то, что я делаю не так? Пожалуйста, дайте мне знать, как сжимать и сохранять файлы в файле, а не только в [NS] Data , как в большинстве ответов в StackOverflow.

1 Ответ

1 голос
/ 20 января 2020

ZIP - это формат файла архива, который также поддерживает сжатие (но он также может содержать несжатые файлы).

ZIP-архив содержит больше, чем просто содержимое сжатого файла. Он также поддерживает индекс всех файлов, каталогов и символических ссылок. Этот индекс называется Central Directory и добавляется в конец файла. Кроме того, к каждому файлу в архиве также прикрепляются некоторые метаданные. Этот локальный заголовок файла содержит такую ​​информацию, как дата создания файла, атрибуты файла, пути к файлу, ...
Вы можете найти полную спецификацию формата ZIP здесь .

Я опубликовал небольшой фреймворк, который можно использовать для работы с ZIP-архивами в Swift: https://github.com/weichsel/ZIPFoundation

Используя этот фреймворк, вы можете создать архив из одного файл, используя следующий код:

let fileManager = FileManager()
let currentWorkingPath = fileManager.currentDirectoryPath
var sourceURL = URL(fileURLWithPath: currentWorkingPath)
sourceURL.appendPathComponent("file.txt")
var destinationURL = URL(fileURLWithPath: currentWorkingPath)
destinationURL.appendPathComponent("archive.zip")
do {
    try fileManager.zipItem(at: sourceURL, to: destinationURL)
} catch {
    print("Creation of ZIP archive failed with error:\(error)")
}
...