(java) HttpEntity.getContent() 输出有限的 InputStream (8192b / 7748b) ...我正在尝试下载一个 2.4MB 的文件
(java) HttpEntity.getContent() outputs limited InputStream (8192b / 7748b) ... I'm trying to download a 2.4MB file
我正在使用 Apache HttpClient 4.5,尝试下载 2.4 MB 文件。 文件可用且可完全下载 Chrome。
问题是,entity.getContent()
返回的 InputStream is
仅包含 8192 字节的缓冲区,而 is.available()
returns 7748. contentLength
的私有字段 is
是2488649,应该是想要的文件大小,所以没看懂是什么问题。我在 Debug 的 Variables 模块中找到的所有缓冲区大小都是 8192。
我已经 尝试用 FileInputStream
替换 现场 is
以我计算机上的相同文件为目标。 传输完美,全部 2.4 MB。所以我想我在 http utils 配置上做错了。
请帮我解决这个问题。代码好像有点长,但是应该很容易看懂。
CommRunnable。以下 class 的基础 class:
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:
Returns an estimate of the number of bytes that can be read (or
skipped over) from this input stream without blocking by the next
invocation of a method for this input stream.
因此可用字节不是总输入字节,而是开始读取输入时缓冲的第一个字节块。 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);
}
我正在使用 Apache HttpClient 4.5,尝试下载 2.4 MB 文件。 文件可用且可完全下载 Chrome。
问题是,entity.getContent()
返回的 InputStream is
仅包含 8192 字节的缓冲区,而 is.available()
returns 7748. contentLength
的私有字段 is
是2488649,应该是想要的文件大小,所以没看懂是什么问题。我在 Debug 的 Variables 模块中找到的所有缓冲区大小都是 8192。
我已经 尝试用 FileInputStream
替换 现场 is
以我计算机上的相同文件为目标。 传输完美,全部 2.4 MB。所以我想我在 http utils 配置上做错了。
请帮我解决这个问题。代码好像有点长,但是应该很容易看懂。
CommRunnable。以下 class 的基础 class:
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:
Returns an estimate of the number of bytes that can be read (or skipped over) from this input stream without blocking by the next invocation of a method for this input stream.
因此可用字节不是总输入字节,而是开始读取输入时缓冲的第一个字节块。 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);
}