Загрузите файлы, используя модификацию 2 без экземпляра файла (filedescriptor или inputtream), или получите экземпляр файла из содержимого URI - PullRequest
0 голосов
/ 17 марта 2020

Я уже загрузил файл с модификацией, используя formdata и @Part, но у меня всегда был экземпляр файла, и я мог легко преобразовать его в тело запроса с помощью функции расширения asRequestBody, включенной в класс RequestBody.

Но теперь мне нужно использовать другой подход. В моем приложении у пользователя нет ограничений по типу файла (это может быть изображение, PDF или что-то еще), поэтому, согласно документации , я использую следующий подход:

val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
            addCategory(Intent.CATEGORY_OPENABLE)
            type = "*/*"
}
requireActivity().startActivityForResult(intent, REQUEST_CODE_PICK_ID)

Работает, и после выбора файла я получаю URI содержимого файла в onActivityResult. Я могу запросить контент-провайдера, чтобы получить небольшой объем информации (например, имя файла), и я могу конвертировать uri контента в дескриптор файла или входной поток, используя распознаватель контента. Но у меня нет экземпляра файла, который мне нужно использовать для преобразования файла в RequestBody.

Я могу получить байтовый массив из входного потока и использовать его (в теле запроса есть другая функция расширения), но правильный ли это подход? Если файл большой, может ли он быть плохим с точки зрения производительности?

Я мог бы создать копию файла, используя inputtream, но мне не нравится этот подход, официальная документация говорит, что вместо него следует использовать open_document get_content как действие намерения избежать создания копии файла.

Итак, как я могу использовать файловый дескриптор или входной поток с модификацией? Есть способ получить экземпляр File из содержимого uri?

1 Ответ

1 голос
/ 17 марта 2020

Вы можете получить объект Input stream у провайдера контента, передав свой Uri, как только вы получите его, чтобы преобразовать поток ввода в массив байтов, следуя приведенному ниже коду

. Вы можете использовать Apache Commons IO для решения этой и подобных задач. .

Тип IOUtils имеет метод stati c для чтения InputStream и возврата байта [].

InputStream is;
byte[] bytes = IOUtils.toByteArray(is);

В Retrofit 2.7.1 Существует класс расширения с именем Body Request. Существует метод расширения для преобразования байтового массива в тело запроса

   @JvmOverloads
@JvmStatic
@JvmName("create")
fun ByteArray.toRequestBody(
  contentType: MediaType? = null,
  offset: Int = 0,
  byteCount: Int = size
): RequestBody {
  checkOffsetAndCount(size.toLong(), offset.toLong(), byteCount.toLong())
  return object : RequestBody() {
    override fun contentType() = contentType

    override fun contentLength() = byteCount.toLong()

    override fun writeTo(sink: BufferedSink) {
      sink.write(this@toRequestBody, offset, byteCount)
    }
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...