问题描述
我正在使用Apache HttpClient 4.5 ,试图下载2.4 MB的文件 。 文件在Chrome中可用并且可以完全下载。
问题是, InputStream is
由归国entity.getContent()
只包含8192字节的缓冲区,并is.available()
返回7748.私人提起contentLength
的is
为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...//
}
请告诉我是否应该添加更多信息。
1楼
从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);
}