繁体   English   中英

在Android中使用HttpPost获取文件上传进度

[英]Get Progress of File Upload using HttpPost in Android

我正在尝试使用HttpPost获得实际文件上传的进度。 到目前为止,我有一个稳定的解决方案(我在SO上找到了),但是有一个进度,但是在上传大文件后,我意识到它只计算写入输出缓冲区的字节,而不计算传输后的进度。 我想以某种方式获得实际“职位”的进展。 有人能解释一下我如何才能用到目前为止所付出的努力来实现这一目标吗? 我在网上找到的大多数解决方案都只计算写入输出缓冲区的字节数(对于小文件来说已经足够了,但在传输大文件时就不足够了)。

公共静态字符串postFile(最终上下文上下文,字符串fileName)抛出异常{

    HttpClient client = new DefaultHttpClient();
    HttpPost post = new HttpPost("http://my.url/");
    MultipartEntityBuilder builder = MultipartEntityBuilder.create();        
    builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);

    final File file = new File(fileName);
    final long totalSize = file.length();
    FileBody fb = new FileBody(file);

    builder.addPart("uploaded_file", new FileBody(new File(fileName)));


    final HttpEntity yourEntity = builder.build();

    int progressPercent = 0;

    class ProgressiveEntity implements HttpEntity {
        @Override
        public void consumeContent() throws IOException {
            yourEntity.consumeContent();                
        }
        @Override
        public InputStream getContent() throws IOException,
                IllegalStateException {
            return yourEntity.getContent();
        }
        @Override
        public Header getContentEncoding() {             
            return yourEntity.getContentEncoding();
        }
        @Override
        public long getContentLength() {
            return yourEntity.getContentLength();
        }
        @Override
        public Header getContentType() {
            return yourEntity.getContentType();
        }
        @Override
        public boolean isChunked() {             
            return yourEntity.isChunked();
        }
        @Override
        public boolean isRepeatable() {
            return yourEntity.isRepeatable();
        }
        @Override
        public boolean isStreaming() {             
            return yourEntity.isStreaming();
        } // CONSIDER put a _real_ delegator into here!

        @Override
        public void writeTo(OutputStream outstream) throws IOException {

            class ProxyOutputStream extends FilterOutputStream {

                public ProxyOutputStream(OutputStream proxy) {
                    super(proxy);    
                }
                public void write(int idx) throws IOException {
                    out.write(idx);
                }
                public void write(byte[] bts) throws IOException {
                    out.write(bts);
                }
                public void write(byte[] bts, int st, int end) throws IOException {
                    out.write(bts, st, end);
                }
                public void flush() throws IOException {
                    out.flush();
                }
                public void close() throws IOException {
                    out.close();
                }
            } // CONSIDER import this class (and risk more Jar File Hell)

            class ProgressiveOutputStream extends ProxyOutputStream {
                long totalSent;
                public ProgressiveOutputStream(OutputStream proxy) {
                       super(proxy);
                       totalSent = 0;
                }

                public void write(byte[] bts, int st, int end) throws IOException {

                // end is the amount being sent this time
                // st is always zero and end=bts.length()

                     totalSent += end;
                     int progress = (int) ((totalSent / (float) totalSize) * 100);
                     out.write(bts, st, end);
                }
            }

            yourEntity.writeTo(new ProgressiveOutputStream(outstream));
        }

    };



    ProgressiveEntity myEntity = new ProgressiveEntity();

    post.setEntity(myEntity);

    //Output to buffer is complete at this point!
    HttpResponse response = client.execute(post);        

    String jsonResponseStr = getContent(response);

    Log.d("MYTAG",jsonResponseStr);

    return jsonResponseStr;

} 

在远程服务器上的接收脚本中,我仅回显一个字符串,以便可以发送立即响应(根本没有文件/数据库处理),并且服务器的响应仍然需要很长时间。 我坚信在这一点上,传输会在写入缓冲区完成之后发生。

class ProgressiveOutputStream extends ProxyOutputStream {
            long totalSent;
            public ProgressiveOutputStream(OutputStream proxy) {
                   super(proxy);
                   totalSent = 0;
            }

            public void write(byte[] bts, int st, int end) throws IOException {

            // FIXME  Put your progress bar stuff here!
            // end is the amount being sent this time
            // st is always zero and end=bts.length()

                 totalSent += end;
                 progress.publish((int) ((totalSent / (float) totalSize) * 100));
                 out.write(bts, st, end);
            }

由于我看不到任何解决方案,因此我想答案是使用没有进度百分比的旋转动画。 因为在传输完成之前什么也不能做。 哦,好吧……至少解决了我的问题。

也许您可以在每次调用write时刷新数据:

totalSent += end;
int progress = (int) ((totalSent / (float) totalSize) * 100);
out.write(bts, st, end);
out.flush(); //flush

编辑:您也可以尝试执行此操作,因为我感觉到end表示out的结束索引out

totalSent += (end-st);

我知道这已经很老了,但是我刚刚找到了解决方案。 如果totalSize是您实体的内容长度,那么您可以基于以下内容进行进度:

class ProgressiveOutputStream extends ProxyOutputStream {
                    long totalSent;
                    long totalSize;
                    public ProgressiveOutputStream(OutputStream proxy, long total) {
                        super(proxy);
                        totalSent = 0;
                        totalSize = total;
                    }
                    public void write(byte[] bts, int st, int end) throws IOException {
                        totalSent += end;
                        publishProgress((int) ((totalSent / (float) totalSize) * 100));
                        out.write(bts, st, end);
                    }
                }

                yourEntity.writeTo(new ProgressiveOutputStream(outstream, yourEntity.getContentLength()));

您可以在asyncTask的OnProgressUpdate中更新进度条(pb是progressBar):

@Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
        pb.setProgress(values[0]);
    }

请尝试下一个解决方案,而ProxyOutputStreamwriteTo方法中使用ProxyOutputStream

@Override 
public void writeTo(OutputStream outstream) throws IOException {
    ByteArrayInputStream reader = new ByteArrayInputStream(mImageData);
    byte[] fileBuffer = new byte[2048];
    int bytesRead;
    while ((bytesRead = reader.read(fileBuffer)) != -1) {
        outstream.write(fileBuffer, 0, bytesRead);
        int progress = bytesRead;
    }
    reader.close();
    yourEntity.writeTo(outstream);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM