Cum de a încărca fișiere mari la server folosind retrofit multipart

0

Problema

Am cerere care funcționează bine în poștaș:

enter image description here

și am încercat să-l facă cu Retrofit. În general dimensiuni de fișier va fi >500MB asta. Am făcut o astfel de metoda încărcare:

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

dar am nevoie pentru a avea fișierul pentru a încărca. Pot crea fișier temporar cu astfel de modalitate:

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

dar eu de obicei primesc outOfMemoryException. Am adăugat, de asemenea, la AndroidManifest.xml heap param:

android:largeHeap="true"

dar nu mă ajută deloc în fișierul temp crearea. Nu știu cum poștașul încărcări de fișiere, dar în general am reușit să incarca cu ajutorul lui fișier cu dimensiunea de aproximativ 600Mb. Pot, de asemenea, tăiate de fișier selectat cu bucăți:

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

toate acțiunile vor fi realizate în:

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

             }
         }

deci nu va avea nici o cale de fișier în mod normal. Oricum cred că am făcut ceva greșit.

UPDATE

acum am un astfel de fișier încărcarea din 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 de a primi o astfel de eroare:

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

dar nu pot incarca cu acest cod de fișiere cu o dimensiune de aproximativ 90 mb

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

Cel mai bun răspuns

1

Retrofit cu mai multe chestii are un membru care are un Uri pentru o cerere organismului.

Încercați să utilizați unul pentru un Fisier exemplu.

2021-11-24 07:53:27

puteți clarifica pls care personal, pentru că am văzut această întrebare stackoverflow.com/questions/34562950/... și utilizate de personalul de la el
Andrew

Ai văzut somerhing pentru un uri acolo? Pentru un flux de intrare?
blackapps

Google pentru inputstreamrequestbody.
blackapps

Am încercat să folosesc flux de intrare cum ai spus, dar cu matrice octet de utilizare, și-mi încărcarea metodă eșuează în mărime fișier > 90mb, puteți verifica întrebarea mea upd pls?
Andrew

Am să spun doar să utilizați uri. Se pare că nu faci asta. Tu nu ar trebui să folosească o matrice octet. Sau un flux de intrare. Ei bine... Nu în acest fel.
blackapps

poate puteți adăuga câteva exemple, pentru că am făcut-o ca te-a inteles, poate tu stii mai bine ca mine?) pentru că nu am găsit nici o mențiune despre uri pentru a requestbody
Andrew

0

Ai set jurnal în loggingInterceptor sau restadapter ?
dacă da, atunci încercați să-l setați NICIUNUL.

2021-11-24 06:14:28

este deja făcut
Andrew

În alte limbi

Această pagină este în alte limbi

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