Загрузить несколько файлов с индикатором выполнения, используя OKHTTP3 - PullRequest
0 голосов
/ 23 марта 2020
public class CountingFileRequestBody extends RequestBody {

    private static final int SEGMENT_SIZE = 2048; // okio.Segment.SIZE

    private final File file;
    private final ProgressListener listener;
    private final String contentType;

    public CountingFileRequestBody(File file, String contentType, ProgressListener listener) {
        this.file = file;
        this.contentType = contentType;
        this.listener = listener;
    }

    @Override
    public long contentLength() {
        return file.length();
    }

    @Override
    public MediaType contentType() {
        return MediaType.parse(contentType);
    }

    @Override
    public void writeTo(BufferedSink sink) throws IOException {
        Source source = null;
        try {
            source = Okio.source(file);
            long total = 0;
            long read;

            while ((read = source.read(sink.buffer(), SEGMENT_SIZE)) != -1) {
                total += read;
                sink.flush();
                this.listener.transferred(total);

            }
        } finally {
            Util.closeQuietly(source);
        }
    }

    public interface ProgressListener {
        void transferred(long num);
    }

}

Я видел приведенный выше код для получения прогресса загрузки файла ... И код используется следующим образом

RequestBody requestBody = new MultipartBuilder()
        .type(MultipartBuilder.FORM)
        .addPart(
                Headers.of("Content-Disposition", "form-data; name=\"image\"; filename=\"" + file.getName() + "\""),
                new CountingFileRequestBody(file, "image/*", new CountingFileRequestBody.ProgressListener() {
                    @Override
                    public void transferred(long num) {
                        float progress = (num / (float) totalSize) * 100;
                        uploadData.progressValue = (int) progress;
                        handler.post(new Runnable() {
                            @Override
                            public void run() {
                                updateProgressBar(tempId);
                            }
                        });
                    }
                })
        )
        .build();
Request request = new Request.Builder()
        .tag(tempId)
        .url(Constants.BASE_URL + apiPath)
        .post(requestBody)
        .build();

Но код работает только для загрузки одного файла, я все еще плохо знакомы с JAVA, поэтому я не знаю, как изменить код, чтобы он подходил для загрузки нескольких файлов ...

Ниже приведен мой код для загрузки файлов

MultipartBody.Builder multipartBody = new MultipartBody.Builder().setType(MultipartBody.FORM);
for (int g = 0; g < fileLists.size(); g++){
    File file = fileLists.get(g);
    multipartBody.addFormDataPart("files[]", file.getName(), RequestBody.create(MediaType.parse("*/*"), file));
}
multipartBody.addFormDataPart("lang", lang)
        .addFormDataPart("user", myIDtoString)
        .addFormDataPart("post", postText);
RequestBody requestBody = multipartBody.build();
Request request = new Request.Builder()
        .url(Constants.submitPostUrl)
        .post(requestBody)
        .build();

Пожалуйста, Как я могу изменить код класса Java, чтобы он соответствовал моему коду загрузки

1 Ответ

0 голосов
/ 27 марта 2020

Наконец-то у меня все заработало после долгого поиска

Вот мой класс , не нацеленный на один запрос файла, а все тело запроса

public class CountingRequestBody extends RequestBody {
    protected RequestBody delegate;
    protected Listener listener;

    protected CountingSink countingSink;

    public CountingRequestBody(RequestBody delegate, Listener listener)
    {
        this.delegate = delegate;
        this.listener = listener;
    }

    @Override
    public MediaType contentType()
    {
        return delegate.contentType();
    }

    @Override
    public long contentLength()
    {
        try
        {
            return delegate.contentLength();
        } catch (IOException e)
        {
            e.printStackTrace();
        }
        return -1;
    }

    @Override
    public void writeTo(BufferedSink sink) throws IOException
    {

        countingSink = new CountingSink(sink);
        BufferedSink bufferedSink = Okio.buffer(countingSink);

        delegate.writeTo(bufferedSink);

        bufferedSink.flush();
    }

    protected final class CountingSink extends ForwardingSink
    {

        private long bytesWritten = 0;

        public CountingSink(Sink delegate)
        {
            super(delegate);
        }

        @Override
        public void write(Buffer source, long byteCount) throws IOException
        {
            super.write(source, byteCount);

            bytesWritten += byteCount;
            listener.onRequestProgress(bytesWritten, contentLength());
        }

    }

    public static interface Listener
    {
        public void onRequestProgress(long bytesWritten, long contentLength);
    }
}

Загрузка нескольких файлов

public void filesUploader(){
    MultipartBody.Builder multipartBody = new MultipartBody.Builder().setType(MultipartBody.FORM);
    for (int g = 0; g < itemLists.size(); g++){
        File readFile = itemLists.get(g);
        Uri uris = Uri.fromFile(readFile);
        String fileExt = MimeTypeMap.getFileExtensionFromUrl(uris.toString());
        String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileExt.toLowerCase());
        multipartBody.addFormDataPart("files[]", readFile.getName(), RequestBody.create(MediaType.parse(mimeType), readFile));
    }
    multipartBody.addFormDataPart("someparams1", value1)
            .addFormDataPart("someparams2", value2);

    final CountingRequestBody.Listener progressListener = new CountingRequestBody.Listener() {
        @RequiresApi(api = Build.VERSION_CODES.N)
        @Override
        public void onRequestProgress(long bytesRead, long contentLength) {
            if (bytesRead >= contentLength) {
            } else {
                if (contentLength > 0) {
                    final int progress = (int)Math.round((((double) bytesRead / contentLength) * 100));
                    postProgressBar.setProgress(progress, true);
                    postProgressText.setText(progress+"%");
                    if(progress == 100){

                    }
                }
            }
        }
    };

    OkHttpClient imageUploadClient = new OkHttpClient.Builder()
            .addNetworkInterceptor(new Interceptor() {
                @Override
                public Response intercept(Chain chain) throws IOException {
                    Request originalRequest = chain.request();

                    if (originalRequest.body() == null) {
                        return chain.proceed(originalRequest);
                    }
                    Request progressRequest = originalRequest.newBuilder()
                            .method(originalRequest.method(),
                                    new CountingRequestBody(originalRequest.body(), progressListener))
                            .build();

                    return chain.proceed(progressRequest);

                }
            })
            .build();
    RequestBody requestBody = multipartBody.build();
    Request request = new Request.Builder()
            .url(Constants.submitPostUrl)
            .header("Accept", "application/json")
            .header("Content-Type", "application/json")
            .post(requestBody)
            .build();


    imageUploadClient.newCall(request).enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            String mMessage = e.getMessage().toString();
            //onError
            Log.e("failure Response", mMessage);
        }

        @RequiresApi(api = Build.VERSION_CODES.N)
        @Override
        public void onResponse(Call call, Response response) throws IOException {
            String mMessage = response.body().string();
            //successful
        }
    });
}
...