Загрузка PDF из совместно используемого локального хранилища в iOS (Drive, OneDrive, Dropbox..) на сервер с помощью Ktor не удалась.

Вопрос или проблема

Я разрабатываю функцию для своего приложения, которая позволяет пользователю загружать PDF из общего хранилища на устройстве (Drive, OneDrive, Dropbox и т.д.) Я использую Kotlin Multiplatform 2.0.20

Это код, который я использую для загрузки PDF для iOS, он работает хорошо для файлов, выбранных из iCloud, загруженных локально на устройстве и Dropbox, но НЕ для Google Drive и OneDrive

    val documentPickerController = UIDocumentPickerViewController(
        forOpeningContentTypes = listOf(UTTypePDF)
    )
    documentPickerController.allowsMultipleSelection = false
    val documentDelegate = remember {
        object : NSObject(), UIDocumentPickerDelegateProtocol {
            override fun documentPicker(
                controller: UIDocumentPickerViewController,
                didPickDocumentAtURL: NSURL
            ) {
                val accessing =
                    didPickDocumentAtURL.startAccessingSecurityScopedResource()
                val data = try {
                    NSData.dataWithContentsOfURL(didPickDocumentAtURL)
                } catch (e: Error) {
                    e.printStackTrace()
                    null
                }

                if (accessing == true) {
                    didPickDocumentAtURL.stopAccessingSecurityScopedResource()
                }
                controller.dismissViewControllerAnimated(true, null)
            }
        }
    }

При отладке я обнаружил, что проблема в этой строке: NSData.dataWithContentsOfURL(didPickDocumentAtURL), она возвращает null

Исключение не выбрасывается, и даже размещение этого кода в блоке try/catch не помогло понять ошибку, стоящую за значением null.

У меня нет экспертизы в ObjectiveC или Swift, поэтому я обращаюсь за вашей помощью 🙂

Спасибо!

Ответ или решение

Чтобы загрузить PDF-файл из общего хранилища на iOS (таких как Google Drive, OneDrive, Dropbox и т. д.) на сервер с использованием Ktor, необходимо учесть несколько особенностей, касающихся доступа к файлам из различных облачных сервисов. Ваше основное затруднение заключается в том, что метод NSData.dataWithContentsOfURL возвращает null для файлов, выбранных из Google Drive и OneDrive, но работает нормально с iCloud и Dropbox.

Анализ проблемы

  1. Безопасный доступ к ресурсам: При выборе документа через UIDocumentPickerViewController, ваша задача – обеспечить безопасный доступ к этим ресурсам. Для этого вы правильно используете методы startAccessingSecurityScopedResource и stopAccessingSecurityScopedResource.

  2. Сетевые ограничения: Google Drive и OneDrive могут обрабатывать файлы иначе, чем локальные хранилища. При этом доступ к этим файлам может требовать дополнительных прав или аутентификации, что может вызывать проблемы с получением данных.

  3. Проблема с NSData: Если метод NSData.dataWithContentsOfURL возвращает null, это может указывать на то, что файл не может быть загружен. Причины могут варьироваться от отсутствия доступа до формата файла, который не поддерживается. Поскольку вы заранее не получаете ошибок, есть возможность, что это связано с тем, как кладываются файлы в ресурсах, доступных для чтения.

Рекомендации по решению проблемы

1. Проверьте права доступа

Убедитесь, что вашему приложению предоставлены необходимые разрешения для доступа к документам. Убедитесь, что ваше приложение имеет доступ к документам на уровне системных настроек.

2. Тестируйте с помощью NSData в другой форме

Попробуйте использовать другой подход для считывания данных из файла. Вместо использования NSData.dataWithContentsOfURL, вы можете проверить, доступен ли файл перед тем, как попытаться извлечь из него данные. Например:

val fileExists = NSFileManager.defaultManager.fileExistsAtPath(didPickDocumentAtURL.path)
if (fileExists) {
    val data = NSData.dataWithContentsOfURL(didPickDocumentAtURL, null)
    if (data != null) {
        // Обработка данных
    } else {
        println("Не удалось загрузить данные")
    }
} else {
    println("Файл не найден")
}

3. Используйте альтернативные способы доступа к файлам

Если NSData.dataWithContentsOfURL не срабатывает, рассмотрите возможность использования FileHandle или InputStream:

val fileHandle = NSFileHandle.fileHandleForReadingURL(didPickDocumentAtURL)
val data = fileHandle.readDataToEndOfFile()

4. Логирование и отладка

Добавьте детализированное логирование в ваш код, чтобы лучше понять, что именно происходит. Вы можете использовать отладочные сообщения для вывода информации о текущем URL, а также о результатах вызова методов.

Заключение

Ваш код вполне адекватен для обработки выбора файлов в iOS, и проблема, скорее всего, связана с особенностями доступа к ресурсам из облачных сервисов. Изучив приведенные выше рекомендации, вы сможете более эффективно управлять загрузкой PDF-файлов из Google Drive и OneDrive в ваше приложение. Если проблема не решится, рекомендуется обратиться к документации Apple по UIDocumentPicker или сообществу разработчиков для более специфичной поддержки.

Оцените материал
Добавить комментарий

Капча загружается...