Comment faire pour télécharger de gros fichier sur le serveur à l'aide de rénovation en plusieurs parties

0

La question

J'ai de la demande qui fonctionne bien en facteur:

enter image description here

et je suis en train de le faire avec de Rénovation. En général, la taille des fichiers est >500 MO qui. J'ai fait une telle méthode de téléchargement:

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

mais j'ai besoin de fichier pour le téléchargement. Je peux créer le fichier temporaire avec une telle manière:

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

mais j'ai l'habitude de recevoir outOfMemoryException. J'ai également ajouté à la AndroidManifest.xml tas param:

android:largeHeap="true"

mais ça ne m'aide pas à tous les cours de temp file de la création. Je ne sais pas comment le facteur télécharge les fichiers, mais en général, j'ai réussi à télécharger avec son fichier d'aide avec une taille d'environ 600 mo d'espace disque. Je coupe aussi le fichier sélectionné avec des morceaux:

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

toutes les mesures seront prises dans:

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

             }
         }

donc je n'aurai pas de chemin d'accès au fichier en mode normal. De toute façon je pense que j'ai fait quelque chose de mal.

Mise à JOUR

maintenant, j'ai du téléchargement du fichier de 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)
        }
    }

et de recevoir une telle erreur:

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

mais je peux télécharger avec ce fichier de code avec une taille d'environ 90 mo

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

La meilleure réponse

1

La rénovation multipart trucs a un membre qui prend une Uri pour un corps de la requête.

Vous essayez d'utiliser un Fichier d'exemple.

2021-11-24 07:53:27

pouvez-vous préciser pls personnel, parce que j'ai vu cette question stackoverflow.com/questions/34562950/... et le personnel de lui
Andrew

Avez-vous vu somerhing pour un uri là? Pour un flux d'entrée?
blackapps

Google pour inputstreamrequestbody.
blackapps

J'ai essayé d'utiliser le flux d'entrée comme vous l'avez dit, mais avec tableau d'octets d'utilisation, et ma méthode de téléchargement échoue sur la taille du fichier > 90 mo, pouvez-vous vérifier ma question upd pls?
Andrew

Je n'ai fait que dire d'utiliser l'uri. Il semble que vous ne le faisons pas. Vous ne devriez pas utiliser un tableau d'octets. Ou un flux d'entrée. Eh bien... Pas de cette façon.
blackapps

peut-être que vous pouvez ajouter des exemples, parce que je n'ai comme compris vous, peut-être que vous le savez mieux que moi?) parce que je n'ai pas trouvé mention sur l'uri pour requestbody
Andrew

0

Avez-vous mis le journal dans loggingInterceptor ou restadapter ?
si oui, alors essayez de le régler AUCUN.

2021-11-24 06:14:28

c'est déjà fait
Andrew

Dans d'autres langues

Cette page est dans d'autres langues

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