Jak przesłać duży plik na serwer za pomocą zmodyfikowanego złożonego

0

Pytanie

Mam prośbę, która działa dobrze w postman:

enter image description here

i staram się zrobić to za pomocą modernizacji. W ogólnym przypadku rozmiary plików są >500 MB, co jest. Zrobiłem taki sposób ładowania:

fun uploadFile(file:File) {

        val client = OkHttpClient().newBuilder()
            .build()
        val mediaType: MediaType? = "text/plain".toMediaTypeOrNull()
        val body: RequestBody = MultipartBody.Builder().setType(MultipartBody.FORM)
            .addFormDataPart(
                "data", file.name,
                file.asRequestBody()
            )
            .build()
        val request: Request = Request.Builder()
            .url("https://..../upload.php")
            .method("POST", body)
            .build()
        val response: okhttp3.Response = client.newCall(request).execute()

       println(response.message)
    }

ale potrzebny mi jest plik do pobrania. Mogę utworzyć pliku tymczasowego w taki sposób:

val path = requireContext().cacheDir
val file = File.createTempFile(
    name ?: "",
    fileUri.lastPathSegment,
    path
)
val os = FileOutputStream(file)
os.write(string)
os.close()

ale ja zwykle dostaję outOfMemoryException. Dodałem też do AndroidManifest.xml parametry stosu:

android:largeHeap="true"

ale to wcale nie pomogło mi podczas tworzenia pliku tymczasowego. Nie wiem, jak listonosz pobiera pliki, ale w ogóle udało mi się pobrać z jego pomocą plik o wielkości około 600 MB. Ja też mogę wyciąć wybrany plik kawałki:

val data = result.data
data?.let {
      val fileUri = data.data
      var name: String? = null
      var size: Long? = null
      fileUri.let { returnUri ->
            contentResolver?.query(returnUri!!, null, null, null, null)
      }?.use { cursor ->
            val nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
            val sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE)

            cursor.moveToFirst()
            name = cursor.getString(nameIndex)
            size = cursor.getLong(sizeIndex)
       }


val inputStream: InputStream? = fileUri?.let { it1 ->
    contentResolver.openInputStream(
        it1
    )
}

val fileData = inputStream?.readBytes()
val mimeType = fileUri.let { returnUri ->
returnUri.let { retUri ->
    if (retUri != null) {
           contentResolver.getType(retUri)
    }
}
}


fileData?.let {
       val MAX_SUB_SIZE = 4194304 // 4*1024*1024 == 4MB
       var start = 0 // From 0
       var end = MAX_SUB_SIZE // To MAX_SUB_SIZE bytes
       var subData: ByteArray // 4MB Sized Array

       val max = fileData.size
       if (max > 0) {
           while (end < max) {
                subData = fileData.copyOfRange(start, end)
                start = end
                end += MAX_SUB_SIZE
                if (end >= max) {
                    end = max
                }
                                
                println("file handling" + subData.size)



        }
     end-- // To avoid a padded zero
     subData = fileData.copyOfRange(start, end)
     println("file handling" + subData.size)
     }
   }
}

wszystkie działania będą realizowane w:

 private val filesReceiver =
        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
            if (result.resultCode == Activity.RESULT_OK) {

             }
         }

więc u mnie nie będzie żadnej ścieżki do pliku w zwykły sposób. W każdym razie, myślę, że zrobił coś nie tak.

Zaktualizować

teraz mam taki pobieranie plików z InputStream:

 private fun doSomeNetworkStuff(file:InputStream, name:String) {
        GlobalScope.launch(Dispatchers.IO) {
            val client = OkHttpClient()
                .newBuilder()
                .protocols(listOf(Protocol.HTTP_1_1))
                .connectTimeout(10, TimeUnit.MINUTES)
                .readTimeout(10, TimeUnit.MINUTES)
                .build()
            val mediaType: MediaType? = "text/plain".toMediaTypeOrNull()
            val body: RequestBody = MultipartBody.Builder().setType(MultipartBody.FORM)
                .addFormDataPart(
                    "data", name,
                    file.readBytes().toRequestBody(mediaType)
                )
                .build()
            val request: Request = Request.Builder()
                .url("https://.../upload.php")
                .method("POST", body)
                .build()

            val response: Response = client.newCall(request).execute()

            println(response.body)
        }
    }

i dostaniesz taki błąd:

java.lang.OutOfMemoryError: Failed to allocate a 173410912 byte allocation with 25165824 free bytes and 89MB until OOM, max allowed footprint 199761800, growth limit 268435456

ale mogę pobrać za pomocą tego pliku kodu o wymiarach około 90 MB

android
2021-11-24 05:56:49
2

Najlepsza odpowiedź

1

W złożonym materiale modernizacji jest element, który przyjmuje Uri dla ciała zapytania.

Próbujesz używać go do instancji pliku.

2021-11-24 07:53:27

czy możesz wyjaśnić, proszę, jaki personel, bo widziałem to pytanie stackoverflow.com/questions/34562950/... i użył laska od niego
Andrew

Widziałeś tam kogoś, kto szukał uri? All inclusive dla strumienia wejściowego?
blackapps

Wyszukaj w Google na życzenie inputstreamrequestbody.
blackapps

Próbowałem użyć strumień wejściowy, jak pan powiedział, ale z wykorzystaniem tablicy bajtów, i moje metody pobierania nie działa przy rozmiarze pliku > 90 MB, czy możesz sprawdzić moje pytanie, proszę?
Andrew

Powiedziałem tylko korzystać z uri. Wygląda na to, że tego nie robisz. Nie trzeba korzystać z tablicy bajtów. Czy strumień wejściowy. Dobrze... Nie w tym sensie.
blackapps

może być, można dodać jakiś wzór, bo zrobiłem to tak, jak zrozumiałem, może wiesz lepiej niż ja?) bo ja nie znalazłem żadnych wzmianek o uri żądania
Andrew

0

Zainstalowałeś login w loggingInterceptor lub restadapter ?
jeśli tak, to spróbuj zainstalować go NIE ma.

2021-11-24 06:14:28

jest to już zrobione
Andrew

W innych językach

Ta strona jest w innych językach

Русский
..................................................................................................................
Italiano
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................