Retrofit multipart kullanarak sunucuya büyük dosya yükleme

0

Soru

Postacıda iyi çalışan bir isteğim var:

enter image description here

ve bunu Güçlendirme ile yapmaya çalışıyorum. Genel olarak dosya boyutları >500MB olacaktır. Böyle bir yükleme yöntemi yaptım:

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

ama yüklenecek dosyaya ihtiyacım var. Bu şekilde geçici bir dosya oluşturabilirim:

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

ama genelde alırım. outOfMemoryException. Ayrıca Androidmanifest'e ekledim.xml yığın param:

android:largeHeap="true"

ama geçici dosya oluşturma sırasında bana hiç yardımcı olmadı. Postacının dosyaları nasıl yüklediğini bilmiyorum, ancak genel olarak yardım dosyasıyla yaklaşık 600Mb boyutunda yüklemeyi başardım. Seçilen dosyayı parçalarla da kesebilirim:

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

tüm eylemler aşağıdaki durumlarda yapılacaktır::

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

             }
         }

bu yüzden normal şekilde herhangi bir dosya yolum olmayacak. Her neyse sanırım yanlış bir şey yaptım.

Güncelleme

şu anda ınputstream'den böyle bir dosya yüklüyorum:

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

ve böyle bir hata alıyorum:

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

ancak bu kod dosyasını yaklaşık 90mb boyutunda yükleyebilirim

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

En iyi cevabı

1

Retrofit multipart stuff, bir istek gövdesi için bir Urı alan bir üyeye sahiptir.

Bir Dosya örneği için birini kullanmayı deneyin.

2021-11-24 07:53:27

lütfen hangi personeli açıklığa kavuşturabilir misiniz, çünkü bu soruyu gördüm stackoverflow.com/questions/34562950 / ... ve ondan personel kullandı
Andrew

Orada bir urı için somerhing gördün mü? Bir giriş akışı için açık mı?
blackapps

ınputstreamrequestbody için Google.
blackapps

Ben denedim kullanmak için giriş stream olarak söyledi, ama bayt dizisi kullanımı ve benim yükleme yöntemi başarısız boyut > yok, sen Çek benim sorum çeviri: pls?
Andrew

Sadece urı'yi kullan demiştim. Görünüşe göre bunu yapmıyorsun. Bayt dizisi kullanmamalısınız. Veya bir giriş akışı. İyi... Bu şekilde değil.
blackapps

belki biraz örnek ekleyebilirsin, çünkü seni anlamış gibi yaptım, belki de benden daha iyi biliyorsun?) çünkü urı hakkında requestbody için herhangi bir söz bulamadım
Andrew

0

loggingInterceptor veya restadapter'da oturum aç'ı ayarladınız mı ?
eğer evet ise, o zaman hiçbirini ayarlamaya çalışın.

2021-11-24 06:14:28

bu zaten yapıldı
Andrew

Diğer dillerde

Bu sayfa diğer dillerde

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