Android Retrofit 2 file upload is not working

2019-05-21 06:41发布

问题:

I want to develop an app which is upload any type of file to sever. I got source code. But it is working only for images. And only upload below 2 MB size of image files. I want to upload all type of files. Please help me. My codes are shown below.

MainActivity.java

public class MainActivity extends AppCompatActivity {
Service service;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Button btn = (Button) findViewById(R.id.btn_upload);

    HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
    interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
    OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();

    // Change base URL to your upload server URL.
    service = new Retrofit.Builder().baseUrl("http://192.168.1.4/work/filesharing/").client(client).build().create(Service.class);

    if (btn != null) {
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                String filePath1 = "/storage/emulated/0/gt.png";

                File file = new File(filePath1);

                RequestBody reqFile = RequestBody.create(MediaType.parse("*/*"), file);
                MultipartBody.Part body = MultipartBody.Part.createFormData("uploaded_file", file.getName(), reqFile);
                RequestBody name = RequestBody.create(MediaType.parse("text/plain"), "upload_test");



                retrofit2.Call<okhttp3.ResponseBody> req = service.postImage(body, name);
                req.enqueue(new Callback<ResponseBody>() {
                    @Override
                    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { }

                    @Override
                    public void onFailure(Call<ResponseBody> call, Throwable t) {
                        t.printStackTrace();

                        Log.d("failure", "message = " + t.getMessage());
                        Log.d("failure", "cause = " + t.getCause());
                    }
                });

            }
        });
    }
}

}

Error will showing when upload the zip file above 2MB.

11-14 17:09:14.369 13895-13960/app3.acs.com.file_upload2 D/OpenGLRenderer: Enabling debug mode 0
11-14 17:09:16.068 13895-13993/app3.acs.com.file_upload2 D/OkHttp: --> POST http://192.168.1.4/work/filesharing/6.php HTTP/1.1
11-14 17:09:16.068 13895-13993/app3.acs.com.file_upload2 D/OkHttp: Content-Type: multipart/form-data; boundary=b2c1d03e-f7a5-4e3f-89e1-d1c20358f7dc
11-14 17:09:16.070 13895-13993/app3.acs.com.file_upload2 D/OkHttp: Content-Length: 20862337
11-14 17:09:16.934 13895-13919/app3.acs.com.file_upload2 W/art: Suspending all threads took: 30.363ms
11-14 17:09:16.935 13895-13993/app3.acs.com.file_upload2 I/art: Alloc partial concurrent mark sweep GC freed 20318(40MB) AllocSpace objects, 0(0B) LOS objects, 35% free, 28MB/44MB, paused 644us total 49.776ms
11-14 17:09:18.272 13895-13993/app3.acs.com.file_upload2 I/art: Alloc sticky concurrent mark sweep GC freed 8(256B) AllocSpace objects, 0(0B) LOS objects, 10% free, 68MB/76MB, paused 1.012ms total 6.892ms
11-14 17:09:18.293 13895-13993/app3.acs.com.file_upload2 I/art: Alloc partial concurrent mark sweep GC freed 6(192B) AllocSpace objects, 0(0B) LOS objects, 18% free, 68MB/84MB, paused 1.310ms total 18.796ms
11-14 17:09:18.330 13895-13993/app3.acs.com.file_upload2 I/art: Alloc concurrent mark sweep GC freed 6(12KB) AllocSpace objects, 0(0B) LOS objects, 18% free, 68MB/84MB, paused 627us total 34.490ms
11-14 17:09:18.332 13895-13993/app3.acs.com.file_upload2 I/art: Forcing collection of SoftReferences for 36MB allocation
11-14 17:09:18.371 13895-13993/app3.acs.com.file_upload2 I/art: Alloc concurrent mark sweep GC freed 11(344B) AllocSpace objects, 0(0B) LOS objects, 18% free, 68MB/84MB, paused 569us total 38.975ms
11-14 17:09:18.373 13895-13993/app3.acs.com.file_upload2 E/art: Throwing OutOfMemoryError "Failed to allocate a 38772598 byte allocation with 16777120 free bytes and 27MB until OOM"
11-14 17:09:18.381 13895-13993/app3.acs.com.file_upload2 E/AndroidRuntime: FATAL EXCEPTION: OkHttp Dispatcher
                                                                       Process: app3.acs.com.file_upload2, PID: 13895
                                                                       java.lang.OutOfMemoryError: Failed to allocate a 38772598 byte allocation with 16777120 free bytes and 27MB until OOM
                                                                           at java.lang.String.<init>(String.java:332)
                                                                           at java.lang.String.<init>(String.java:371)
                                                                           at okio.Buffer.readString(Buffer.java:579)
                                                                           at okio.Buffer.readString(Buffer.java:562)
                                                                           at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:195)
                                                                           at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:187)
                                                                           at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:160)
                                                                           at okhttp3.RealCall.access$100(RealCall.java:30)
                                                                           at okhttp3.RealCall$AsyncCall.execute(RealCall.java:127)
                                                                           at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
                                                                           at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
                                                                           at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
                                                                           at java.lang.Thread.run(Thread.java:818)
11-14 17:09:20.069 13895-13993/app3.acs.com.file_upload2 I/Process: Sending signal. PID: 13895 SIG: 9

回答1:

Please reduce the logging level or remove it all together

Have a look at JakeWharton reply on this link https://github.com/square/retrofit/issues/540

"By calling .setLogLevel(RestAdapter.LogLevel.FULL) you are forcing Retrofit to buffer the entire request body into memory so that it can log. That's what the call to readBodyToBytesIfNecessary in the stack trace is doing.

Enabling logging like this should only be done when debugging."



回答2:

Its related to this issue https://github.com/square/retrofit/issues/540 . You can disable your interceptor Level.BODY. It can be working for all type files, did you tried with other type files?



回答3:

You can refer from here too https://futurestud.io/tutorials/retrofit-2-how-to-upload-files-to-server it will help upload the files



回答4:

I got the answer. It is the problem in xampp server. Now i can send large files. I got the answer from this link How to Increase Import Size Limit in phpMyAdmin using Xampp server?

But the speed is low. Any way it's working as fine.



回答5:

I had the same problem uploading large images or videos. The main problem is you're using body level in HttpLoggingInterceptor, and logger is printing your file in logcat triggering a java.lang.OutOfMemoryError exception.

If you don't want to disable the body level loggin you can add this code to avoid loggin to print big large files content. I created my own HttpLoggingInterceptor and add an if condition to skip body loggin in case of content-length > 10Ks.

HttpLoggingInterceptor is a final class, so you can't override it. You can make a copy of HttpLoggingInterceptor file and replace this original code:

if (!logBody || !hasRequestBody) {
            logger.log("--> END " + request.method());
        } else if (bodyEncoded(request.headers())) {
            logger.log("--> END " + request.method() + " (encoded body omitted)");
        } else {
            Buffer buffer = new Buffer();
            requestBody.writeTo(buffer);
            //[...]

with this code:

if (!logBody || !hasRequestBody) {
            logger.log("--> END " + request.method());
        } else if (bodyEncoded(request.headers())) {
            logger.log("--> END " + request.method() + " (encoded body omitted)");
        } else if (requestBody.contentLength()>1024 * 10) { //>10Kb
            logger.log("--> END " + request.method() + " (contentLength > 10Kb --> omitted)");
        } else {
            Buffer buffer = new Buffer();
            requestBody.writeTo(buffer);
            //[...]

I hope this can help anyone. And sorry for my English ;).



回答6:

I had the same issue But I found There is no issue in the library. My issue is resolved. Its Server side issue. You Might check following point to resolve it:-

  1. Check how lengthy file can be uploaded to the server.
  2. Check server connection time out from the server point of view.
  3. Make sure you have to change the file size on Apache server also. (In my case php filesize of apache server was 5MB)