@Anrek

Почему выходит ошибка No such file or directory при отправке pdf в удаленное хранилище?

Хочу отправить pdf в удаленное хранилище из внутреннего хранилища телефона.

Что делаю:
1) Получаю path pdf файла (uriString в коде).
Код отправки запроса path

val pdfIntent = Intent(Intent.ACTION_GET_CONTENT)
pdfIntent.type = "application/pdf"
pdfIntent.addCategory(Intent.CATEGORY_OPENABLE)
startActivityForResult(pdfIntent, 12)

Код получения ответа с path

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
12 -> if (resultCode == RESULT_OK) {
pdfUri = data?.data!!
val uri: Uri = data?.data!!
val uriString: String = uri.toString()
var pdfName: String? = null
if (uriString.startsWith("content://")) {
var myCursor: Cursor? = null
try {
myCursor = applicationContext!!.contentResolver.query(uri, null, null, null, null)
if (myCursor != null && myCursor.moveToFirst()) {
pdfName = myCursor.getString(myCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME))
pdfTextView.text = pdfName
}
} finally {
myCursor?.close()
}
}
}
}

Результат:
uriString = content://com.android.providers.downloads.documents/document/msf%3A14
pdfName = test.pdf


2) Создаю file
Код создания file

var file: File
try {
file = File(uriString)
} catch (e: Exception) {
Timber.d('${e}')
}


3) Отправляю file
Тело запроса

val requestBody = RequestBody.create(MediaType.parse("application/pdf"), file)


Результат ошибка: java.io.FileNotFoundException: content:/com.android.providers.downloads.documents/document/msf%3A14: open failed: ENOENT (No such file or directory)

Что пробовал делать
Разрешение READ_EXTERNAL_STORAGE проверил, все ок. Пробовал менять path результата нет:
1) content:/com.android.providers.downloads.documents/document/msf%3A14/1.pdf
2) content:/com.android.providers.downloads.documents/document/1.pdf

Вопрос: почему выходит ошибка?
  • Вопрос задан
  • 1128 просмотров
Решения вопроса 1
@Anrek Автор вопроса
Я сделал 2 ошибки:
1) выше апи 29 получать абсолютный путь нельзя (изменили из соображений безопасности) - поэтому выходила ошибка No such file or directory, нужно копировать файл в кеш папку приложения.
2) pdf файл нужно не только создать но и записать туда данные, а я только создал (и после того как исправил ошибку еще долго искал почему на сервер приходит пустой файл).

Итого решение выглядит так (основные шаги)

1) Запускаю окно выбора файла:
Intent
val pdfIntent = Intent(Intent.ACTION_GET_CONTENT)
pdfIntent.type = "application/pdf"
pdfIntent.addCategory(Intent.CATEGORY_OPENABLE)
startActivityForResult(pdfIntent, 12)


2) Переопределяю fun onActivityResult, в ней из полученной в ней data получаю uri и отправляю его сначала в функцию getDriveFilePath(uri)
val uri = data.data
Функция getDriveFilePath создает 2 File() и 2 stream и копирует данные по stream в файл в кеш директории (если не скопировать данные, а только создать файл, на сервер придет пустой файл, и еще важно копировать данные как для символьного файла, а не как для картинки, иначе тоже будет пустой файл).
Функция getDriveFilePath

val file = File(requireContext().getCacheDir(), name)
try {
val instream: InputStream = requireContext().getContentResolver().openInputStream(uri)!!
val output = FileOutputStream(file)
val buffer = ByteArray(1024)
var size: Int
while (instream.read(buffer).also { size = it } != -1) {
output.write(buffer, 0, size)
}
instream.close()
output.close()
} catch (e: IOException) {
Log.d("TAG1", "e: ${e}")
}


3) Отправляем полученный file в retrofit функцию, прикрепляем его к запросу и все.
file.asRequestBody("application/pdf".toMediaTypeOrNull())


Надеюсь это кому-то пригодится, потому что в полном виде для pdf я это нигде не нашел.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы