Ako nahrať veľké súboru na server pomocou retrofit zložené

0

Otázka

Mám žiadosť, ktorá funguje dobre v poštár:

enter image description here

a snažím sa, aby to s Retrofit. Vo všeobecnosti veľkosť súboru budú >500MB, že. Ja som taký nahrávanie metóda:

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 musím mať súboru pre nahrávanie. Môžem vytvoriť dočasný súbor s takýmto spôsobom:

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

ale ja zvyčajne dostane outOfMemoryException. Tiež som pridal na AndroidManifest.xml haldy param:

android:largeHeap="true"

ale ani to nepomohlo, mne vôbec počas dočasný súbor vytvoriť. Neviem, ako poštár obrázky súbory, ale vo všeobecnosti sa mi podarilo nahrať s jeho pomocou súboru s veľkosťou cca 600 mb. Ja si tiež vystrihnúť vybraný súbor s kúskami:

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)
     }
   }
}

všetky akcie sa uskutočnia v:

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

             }
         }

takže nebudem mať žiadne cestu k súboru v obvyklým spôsobom. Každopádne si myslím, že som urobil niečo zle.

AKTUALIZÁCIA

práve teraz mám taký súbor nahrávanie 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)
        }
    }

a prijímať takéto chyby:

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 môžem nahrať s týmto kódom súbor s veľkosťou o 90mb

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

Najlepšiu odpoveď

1

Na retrofit zložené veci, má člen, ktorý trvá Uri žiadosti tela.

Skúste použiť jeden pre Súbor stupňa.

2021-11-24 07:53:27

môžeš objasniť pls ktorého zamestnanci, pretože som videl túto otázku stackoverflow.com/questions/34562950/... a použité zamestnancov od neho
Andrew

Videli ste somerhing pre uri tam? Na vstupného prúdu?
blackapps

Google pre inputstreamrequestbody.
blackapps

Snažil som sa využiť vstupný stream, ako ste povedal, ale s bajt poľa použitie, a môj upload metóda zlyháva na veľkosť súboru > 90mb, môžete skontrolovať, moja otázka upd pls?
Andrew

Urobil som len povedať, aby pomocou uri. Zdá sa, nie ste v tom. Nemali by ste používať byte pole. Alebo vstupný prúd. No... Nie je to tak.
blackapps

možno si môžete pridať niektoré vzorky, pretože som to tak pochopil si, možno viete, lepšie sa v nej, že na mňa?) pretože som nenašiel žiadne zmienky o uri na requestbody
Andrew

0

Už ste nastaviť prihlásiť loggingInterceptor alebo restadapter ?
ak áno, potom sa pokúsiť nastaviť ŽIADNE.

2021-11-24 06:14:28

to je už hotovo
Andrew

V iných jazykoch

Táto stránka je v iných jazykoch

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