当前位置: 代码迷 >> java >> (java)HttpEntity.getContent()输出受限的InputStream(8192b / 7748b)…我正在尝试下载2.4MB文件
  详细解决方案

(java)HttpEntity.getContent()输出受限的InputStream(8192b / 7748b)…我正在尝试下载2.4MB文件

热度:101   发布时间:2023-07-31 11:27:53.0

我正在使用Apache HttpClient 4.5 ,试图下载2.4 MB的文件 文件在Chrome中可用并且可以完全下载。

问题是, InputStream is由归国entity.getContent()只包含8192字节的缓冲区,并is.available()返回7748.私人提起contentLengthis为2488649,这应该是所需的文件大小,所以我不明白问题是什么。 我在“调试”的“变量”模块中找到的所有缓冲区大小均为8192。

试图取代 is在现场用FileInputStream瞄准我的电脑上相同的文件。 传输完美,全部2.4 MB。 所以我想我在http utils配置上做错了什么。

请帮我解决这个问题。 该代码似乎有点长,但是应该很容易理解。

CommRunnable。 下面的类的基类:

public abstract class CommRunnable implements Runnable {
    protected HttpPostAgent agent;
    protected boolean success;

    //...additional methods...//
}

GetFileRunnable。 在单独的线程中运行。 启动连接和文件传输:

public class GetFileRunnable extends CommRunnable implements Runnable {
    private String url;
    private String fileDestination;
    private NameValuePair[] postPairs;

    //...constructor...//

    public void run() 
    {
        synchronized (agent) {
            try {
                HttpClient client = HttpClients.createDefault();

                HttpResponse response = agent.getHttpResponse(client, url, postPairs);

                InputStream is = response.getEntity().getContent();
                FileOutputStream fos = new FileOutputStream(fileDestination);

                success = agent.transfer(is, fos);

                client.getConnectionManager().shutdown();

            } catch (IOException e) {
                e.printStackTrace();
                throw new RuntimeException("IOException in HttpPostAgent.getFile");
            } finally {
                agent.setFree(true);
            }
        }
    }
}

HttpPostAgent。 基本上是Apache http实用程序的控制器。 方法在其上方的注释中进行了描述。

public class HttpPostAgent {
    private int statusPerc;
    private boolean free;

    private Thread thread;
    private CommRunnable currentAction;

    //...constructor...//

    //executes POST request and returns resulting HttpResponse
    HttpResponse getHttpResponse(HttpClient client, String url, NameValuePair... postPairs)
    {
        try {
            List <NameValuePair> nvps = new ArrayList <NameValuePair>();

            for (NameValuePair pair : postPairs)
                nvps.add(pair);

            HttpPost post = new HttpPost(url);
            post.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));

            return client.execute(post);

        } catch (IOException e) {
            throw new RuntimeException("IOException in getHttpResponse(HttpClient client, String url, NameValuePair... postPairs)");
        }
    }

    //...methods...//

    //Starts thread with GetFileRunnable. Included here for Your understanding of my context.
    public void getFileInit(String url, String destinationPath, NameValuePair... postPairs)
    {
        free = false;
        statusPerc = 0;
        currentAction = new GetFileRunnable(this, url, destinationPath, postPairs);
        thread = new Thread(currentAction);
        thread.setPriority(Thread.MIN_PRIORITY);
        thread.setDaemon(true);
        thread.start();
    }

    //...methods...//

    //Transfers a file from one input stream to the other. For downloading from response/entity/content.
    boolean transfer(InputStream is, OutputStream os)
    {
        boolean success = false;

        try {
            int remain = is.available();
            int total = remain;
            int read = 0;
            int chunk = 1024;
            byte[] buffer = new byte[chunk];

            while(remain > 0)
            {
                if(chunk > remain) chunk = remain;

                os.flush();
                is.read(buffer, 0, chunk);
                os.write(buffer, 0, chunk);

                remain -= chunk;
                read += chunk;

                synchronized (this) {
                    statusPerc = (read * 100) / total;
                }
            }
            remain = is.available();

            success = true;

        } catch (IOException e) {
            throw new RuntimeException("IOException in HttpPostAgent.transfer");
        } 

        return success;
    }

    //...methods...//
}

请告诉我是否应该添加更多信息。

InputStream.available()的Javadoc中:

返回可以从此输入流读取(或跳过)而不会被该输入流的方法的下一次调用阻塞的字节数的估计值。

因此,可用字节不是总输入字节,而是开始读取输入时已缓冲的第一个字节块。 8192似乎是您的示例中的缓冲区大小。

因此,您的HttpPostAgent.transfer方法仅有效处理前8192个字节,然后停止。

您可以尝试使用以下替代HttpPostAgent.transfer方法吗?

boolean transfer(InputStream is, OutputStream os) throws IOException
{
    byte buffer[] = new byte[2048];
    int count;
    while ((count = is.read(buffer)) != -1)
        os.write(buffer, 0, count);
}
  相关解决方案