Multipart file progress updating faster than actual upload

£可爱£侵袭症+ 提交于 2021-01-28 19:43:10

问题


I am trying to send a file to server using Multipart. This is how I am sending the request

MultipartRequest request = new MultipartRequest(putURLPath,
                    hashMap,
                    null,
                    new Response.Listener<String>() {
                        @Override
                        public void onResponse(String response) {
                            try {
                                Log.d(TAG, "FILE_UPLOAD_RESPONSE: " + response);
                                Logger.writeToFile(TAG, "FILE_UPLOAD_RESPONSE: " + response);

                                if (fileUploadListener != null)
                                    fileUploadListener.onAttachmentFileUpload(generateImageUploadResponse(false, getURLPath), message, isRetry);
//                                fileDownload(getURLPath);
                            } catch (Exception e) {
                                e.printStackTrace();
                                if (fileUploadListener != null)
                                    fileUploadListener.onAttachmentFileUpload(generateImageUploadResponse(true, ""), message, isRetry);
                            }
                        }
                    }, new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    Logger.writeToFile(TAG, "FILE_UPLOAD_RESPONSE--Error: " + error.getMessage());
                   /* byte[] bytes = ((NetworkResponse)((AuthFailureError)error).networkResponse).data;
                    WAAFILogger.d(TAG, "XML: " + bytes.);*/
                    if (fileUploadListener != null)
                        fileUploadListener.onAttachmentFileUpload(generateImageUploadResponse(true, ""), message, isRetry);
                    error.printStackTrace();
                }
            }, new IMultipartProgressListener() {
                @Override
                public void transferred(long transferred, int progress) {
                    WAAFILogger.d(TAG, "Transferred : " + transferred + "\n" + " Progress : " + progress);

                    try {
                        if (fileUploadListener != null) {
                            fileUploadListener.onProgressChanged(message, progress);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                }
            }, bytesArray) {

                @Override
                public String getBodyContentType() {
                    return fileInfo.fileMimeType;
                }

                @Override
                public Map<String, String> getHeaders() throws AuthFailureError {
                    Map<String, String> params = new HashMap<String, String>();
                    params.put("content-length", String.valueOf(bytesArray.length));
                    params.put("host", IMConstant.XMPP_SERVER + ":9000");

                    Logger.writeToFile(TAG, params.get("content-length"));
                    Logger.writeToFile(TAG, params.get("host"));
                    return params;
                }

            };


            request.setRetryPolicy(com.safarifone.settings.Settings.policy);
            VolleyQueManager.getInstance().addToRequestQueue(request);

I have used a custom request and the link is here Custom Request Repo Link and the code is below

public class MultipartRequest extends Request<String> {

    private final byte[] byteArray;
    MultipartEntityBuilder entity = MultipartEntityBuilder.create();
    //        CounterHttpEntity httpentity;
    HttpEntity httpentity;
    //        CountingHttpEntity httpentity;
    private FileUploadManager.IMultipartProgressListener mProgressListener;

    private final Response.Listener<String> mListener;
    private HashMap<String, File> mFiles;
    private HashMap<String, String> mBody;
    private long fileLength = 0L;

    public MultipartRequest(String url,
                            HashMap<String, File> mFiles,
                            HashMap<String, String> body,
                            Response.Listener<String> listener,
                            Response.ErrorListener errorListener,
                            FileUploadManager.IMultipartProgressListener progressListener, byte[] bytesArray) {

        super(Method.PUT, url, errorListener);

        this.mListener = listener;
        this.mFiles = mFiles;
        this.mBody = body;
        this.fileLength = /*getFileLength()*/ bytesArray.length;
        this.mProgressListener = progressListener;
        this.byteArray = bytesArray;

        entity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
        try {
            entity.setCharset(CharsetUtils.get("UTF-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        buildMultipartEntity();

        httpentity = entity.build();
        /*httpentity.setFileLength(fileLength);
        httpentity.setmProgressListener(progressListener);*/

    }

    private void buildMultipartEntity() {    
        for (Map.Entry<String, File> entry : mFiles.entrySet()) {
            if (entry.getValue() != null) {
                entity.addPart(entry.getKey(), new FileBody(entry.getValue()));
            }
        }

        if (mBody != null) {
            for (Map.Entry<String, String> entry : mBody.entrySet()) {
                if (entry.getValue() != null) {
                    entity.addTextBody(entry.getKey(), entry.getValue());
                }
            }
        }
    }

    private int getFileLength() {
        int lgth = 0;
        for (Map.Entry<String, File> entry : mFiles.entrySet()) {
            if (entry.getValue() != null) {
                lgth += entry.getValue().length();
            }
        }
        System.out.println("lgth = " + lgth);
        return lgth;
    }

    @Override
    public String getBodyContentType() {
        return super.getBodyContentType();
        /*return httpentity.getContentType().getValue();*/
    }

    @Override
    public byte[] getBody() throws AuthFailureError {
        Thread thread = new Thread() {
            @Override
            public void run() {
                super.run();
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                try {
                    bos.write(byteArray, 0, byteArray.length);
                    httpentity.writeTo(new CountingOutputStream(bos, fileLength,
                            mProgressListener));
                } catch (IOException e) {
                    VolleyLog.e("IOException writing to ByteArrayOutputStream");
                }
            }
        };
        thread.start();

        return /*bos.toByteArray()*/ byteArray;
    }

    @Override
    protected Response<String> parseNetworkResponse(NetworkResponse response) {

        try {
            String jsonString = new String(response.data,
                    HttpHeaderParser.parseCharset(response.headers));

            return Response.success(jsonString,
                    HttpHeaderParser.parseCacheHeaders(response));

        } catch (UnsupportedEncodingException e) {
            return Response.error(new ParseError(e));
        }
    }

    @Override
    protected void deliverResponse(String response) {
        mListener.onResponse(response);
    }

    public static class CountingOutputStream extends FilterOutputStream {
        private final FileUploadManager.IMultipartProgressListener progressListener;
        private long transferred;
        private long fileLength;
        private int lastProgress = 0;

        public CountingOutputStream(final OutputStream out, long fileLength,
                                    final FileUploadManager.IMultipartProgressListener listener) {
            super(out);
            this.fileLength = fileLength;
            this.progressListener = listener;
            this.transferred = 0;
        }

        public void write(byte[] buffer, int offset, int length) throws IOException {
            out.write(buffer, offset, length);
            if (progressListener != null) {
                this.transferred += length;
                int progress = (int) ((transferred * 1000.0f) / fileLength);
                if (lastProgress != progress) {
                    this.progressListener.transferred(this.transferred, progress);
                }
            }
        }

        public void write(int oneByte) throws IOException {
            out.write(oneByte);
            if (progressListener != null) {
                this.transferred++;
                int progress = (int) ((transferred * 1000.0f) / fileLength);
                if (lastProgress != progress) {
                    this.progressListener.transferred(this.transferred, progress);
                }
            }
        }
    }

}

as you can see I am calulating the progress in the function -> write of class CountingOutputStream. But the issue i am facing is that the write function calls too fast and due to this progress bar updates fast but the response of successfully file uploaded took long time even after the progress bar is completed. My guess is that write function fast therefore progress bar is updated but somehow file is not uploading that fast due to which it is still taking time after completed progress.


回答1:


At then at the end, after days of searching I found this piece of code which work fine. As you can see I have added Content-type, Content-Length and host in headers. You can leave those if your server doesnot need these. Especially this

((HttpURLConnection) urlconnection).setFixedLengthStreamingMode((int) fileInfo.fileSize);

line helps me in achieving the real thing i wanted to achieve. It helps me in writing the data on server and then progress according to then again write some data to server and then again update the progress. So this is most important line.

public void main(FileInfo fileInfo, String put, String get, Message message, boolean isRetry) {
        URLConnection urlconnection = null;
        try {

            File file = new File(fileInfo.filePath);
            URL url = new URL(put);
            urlconnection = url.openConnection();
            urlconnection.setDoOutput(true);
            urlconnection.setDoInput(true);

            if (urlconnection instanceof HttpURLConnection) {
                ((HttpURLConnection) urlconnection).setRequestMethod("PUT");
                ((HttpURLConnection) urlconnection).setFixedLengthStreamingMode((int) fileInfo.fileSize);
                ((HttpURLConnection) urlconnection).setRequestProperty("Content-type", fileInfo.fileMimeType);
                ((HttpURLConnection) urlconnection).setRequestProperty("Content-length", String.valueOf(fileInfo.fileSize));
                ((HttpURLConnection) urlconnection).setRequestProperty("host", XMPP_SERVER);
                ((HttpURLConnection) urlconnection).connect();
            }

            BufferedOutputStream bos = new BufferedOutputStream(urlconnection.getOutputStream());
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));

            long transferred = 0;
            int i = 0;
            byte[] buffer = new byte[4096];
            while ((i = bis.read(buffer)) > 0) {

                bos.write(buffer, 0, i);
                transferred += i;
                int progress = (int) ((transferred * 1000.0f) / fileInfo.fileSize);
                if (fileUploadListener != null) {
                    fileUploadListener.onProgressChanged(message, progress);

                }
            }


            bis.close();
            bos.close();

            InputStream inputStream;
            int responseCode = ((HttpURLConnection) urlconnection).getResponseCode();
            if ((responseCode >= 200) && (responseCode <= 202)) {

                inputStream = ((HttpURLConnection) urlconnection).getInputStream();
                int j;
                while ((j = inputStream.read()) > 0) {
                    System.out.println(j);
                }

                if (responseCode == 200) {
                    if (fileUploadListener != null)
                                           fileUploadListener.onAttachmentFileUpload(generateImageUploadResponse(false, get), message, isRetry);
                } else {

                    if (fileUploadListener != null)
                        fileUploadListener.onAttachmentFileUpload(generateImageUploadResponse(true, ""), message, isRetry);
                }
            } else {
                inputStream = ((HttpURLConnection) urlconnection).getErrorStream();

                if (fileUploadListener != null)
                    fileUploadListener.onAttachmentFileUpload(generateImageUploadResponse(true, ""), message, isRetry);
            }
            ((HttpURLConnection) urlconnection).disconnect();

        } catch (Exception e) {
            e.printStackTrace();

            if (fileUploadListener != null)
                fileUploadListener.onAttachmentFileUpload(generateImageUploadResponse(true, ""), message, isRetry);
        }
    }


来源:https://stackoverflow.com/questions/61137778/multipart-file-progress-updating-faster-than-actual-upload

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!