วิธีการอัปโหลดแฟ้มใหญ่ไปยังเซิร์ฟเวอร์โดยใช้ retrofit multipart

0

คำถาม

ผมมีสิ่งที่ร้องขอมาต้องการซึ่งทำงานอย่างดีในบุรุษไปรษณีย์:

enter image description here

และฉันกำลังพยายามทำให้มันกับ Retrofit. ในอนายพลขนาดแฟ้มจะเป็น>500MB นั้น ฉันทำเรื่องกำลังอัพโหลดวิธีการ:

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

แต่ฉันจำเป็นต้องมีแฟ้มสื่อสำหรับกำลังอัพโหลด ฉันสามารถสร้างแฟ้มชั่วคราวกับเรื่องทาง:

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

แต่ปกติแล้วฉันจะได้รับ outOfMemoryException. ฉันก็เพิ่มเข้าไป AndroidManifest.xml ชื่นชม param:

android:largeHeap="true"

แต่มันไม่ได้ช่วยฉันตลอดตอนกำลังสร้างแฟ้มชั่วคราวได้. ฉันไม่รู้ว่างบุรุษไปรษณีย์ uploads แฟ้มแต่ท่านนายพลฉันจัดการอัปโหลดกับของแฟ้มช่วยเหลืออยู่กับขนาดของเรื่อง 600Mb. ฉันก็สามารถตัดเลือกแฟ้มกับนวนท่อนที่:

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

ทุกการกระทำจะทำให้อยู่ใน:

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

             }
         }

ดังนั้นฉันคงไม่มีแฟ้มเส้นทางในปกติทาง ยังไงก็ตามฉันคิดว่าฉันทำอะไรบางอย่างผิดพลาด

ปรับปรุง

ตอนนี้ฉันมีแฟ้มกำลังอัพโหลดจาก 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)
        }
    }

และได้รับเช่นข้อผิดพลาดคือ:

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

แต่ฉันสามารถอัพโหลดบรหัสแฟ้มกับขนาดของเรื่อง 90mb

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

คำตอบที่ดีที่สุด

1

ที่ retrofit multipart ของมีสมาชิกนั้นต้องการ Uri สำหรับการร้องของร่างกาย

คุณพยายามจะใช้หนึ่งสำหรับแฟ้มตัวอย่าง

2021-11-24 07:53:27

คุณสามารถช่วยชี้แจ pls ซึ่งพนักงานเพราะฉันเห็นคำถาม stackoverflow.com/questions/34562950/... และเคยพนักงานจากเขา
Andrew

คุณเห็น somerhing เพื่อน uri ที่นั่น? งบสำหรับนำเข้าข้อมูลเสียง?
blackapps

ของกูเกิ้ลสำหรับ inputstreamrequestbody.
blackapps

ฉันพยายามที่จะใช้นำเข้าข้อมูลเสียงอย่างที่คุณบอกว่าแต่ด้วยตามวันที่@item:inlistbox sort อาเรย์การใช้แล้วของฉันกำลังอัพโหลดวิธีการล้มเหลวในขนาดแฟ้ม>90mb คุณสามารถเช็คของฉันคำถาม upd pls?
Andrew

ผมแค่พูดเพื่อใช้ uri. มันดูเหมือนว่าคุณไม่ได้ทำอย่างนั้น คุณไม่ควรจะใช้ตามวันที่@item:inlistbox sort อาเรย์. หรือเป็นข้อมูลสายข้อมูลสื่อนี้ เอ่อ...ไม่ใช่วิธีนี้
blackapps

บางทีคุณอาจจะเพิ่มบางตัวอย่างเพราะฉันทำมันเหมือนจะเข้าใจคุณบางทีคุณอาจรู้ดีกว่าผม?) เพราะฉันไม่ได้เจอพูดถึงเรื่องเรื่อง uri ที่จะ requestbody
Andrew

0

คุณตั้งปูมบันทึกอยู่ใน loggingInterceptor หรือ restadapter?
ถ้าใช่แล้วพยายามที่จะตั้งค่ามันไม่เลย

2021-11-24 06:14:28

มันทำไปแล้ว
Andrew

ในภาษาอื่นๆ

หน้านี้อยู่ในภาษาอื่นๆ

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