=Start=
缘由:
本文主要是对之前记录的「Java中如何发起HTTP请求」一文的补充/修正,当时只考虑了用Java发起GET/POST请求,然后读取返回的文本格式的response信息,在下载文本格式的文件时没啥问题,但是对于binary等非文本格式的文件时就有问题了,这里记录一下解决办法以及产生这个问题的原因,方便以后参考。
正文:
参考解答:
当你想下载一个二进制文件时,不要将 InputStream 嵌入任何的 Reader 类型变量中,而应该是 stream 格式读入,(可以借助于一个字节数组作为缓冲区)然后 stream 格式写出。
如果你在这中间使用了任何类型的 Reader 变量,将内容先转换成了 字符/字符串 再写出至文件,(大概率)就会受到平台编码方式的影响,最后的结果可能就和你预期的不一致了。
If you are trying to read a binary stream, you should NOT wrap the InputStream in a Reader of any kind.Read the data into a byte array buffer using the InputStream.read(byte[], int, int) method. Then write from the buffer to a FileOutputStream.
使用 HttpClient 和 FileUtils.copyInputStreamToFile 以及 FileOutputStream 的方式:
package com.ixyzero.learn.utils;
import org.apache.commons.io.FileUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClientBuilder;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
/**
* Created by ixyzero on 2019/9/14.
*/
public class DownloadBinaryFile {
// HttpURLConnection download from remote url to local file
public static void httpGetBinary2(String url, File file) {
URL obj = null;
HttpURLConnection con = null;
try {
obj = new URL(url);
con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
con.setRequestProperty("User-Agent", "Mozilla/5.0");
int responseCode = con.getResponseCode();
System.out.println("\nSending 'GET' request to URL : " + url);
System.out.println("Response Code : " + responseCode);
InputStream inputStream = con.getInputStream();
byte[] buffer = new byte[4096];
int n;
OutputStream output = new FileOutputStream( file );
while ((n = inputStream.read(buffer)) != -1) {
output.write(buffer, 0, n);
}
output.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (ProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
// HttpClient download from remote url to local file
public static void httpGetBinary(String url, File file) {
HttpClient client = HttpClientBuilder.create().build();
// code below adds HTTP REDIRECT support to GET and POST methods
// HttpClient client = HttpClientBuilder.create().setRedirectStrategy(new LaxRedirectStrategy()).build();
HttpGet request = new HttpGet(url);
request.addHeader("User-Agent", "Mozilla/5.0");
try {
HttpResponse response = client.execute(request);
System.out.println("Response Code : " + response.getStatusLine().getStatusCode());
InputStream inputStream = response.getEntity().getContent();
FileUtils.copyInputStreamToFile(inputStream, file);
} catch (IOException e) {
e.printStackTrace();
} finally {
//
}
}
public static void main(String[] args) {
DownloadBinaryFile downloader = new DownloadBinaryFile();
String url1 = "https://www.cnblogs.com/images/logo_small.gif";
String filepath1 = "/path/to/logo.gif";
String filepath2 = "/path/to/logo2.gif";
downloader.httpGetBinary(url1, new File(filepath1));
downloader.httpGetBinary2(url1, new File(filepath2));
}
}
参考链接:
- How do I use HttpClient in Java to retrieve a binary file?
https://stackoverflow.com/questions/6660243/how-do-i-use-httpclient-in-java-to-retrieve-a-binary-file - Ultimate Guide for Reading Files in Java
https://funnelgarden.com/java_read_file/ - Reading binary file from URLConnection
https://stackoverflow.com/questions/3221979/reading-binary-file-from-urlconnection - Write a binary downloaded file to disk in Java
https://stackoverflow.com/questions/1477269/write-a-binary-downloaded-file-to-disk-in-java - Java HttpURLConnection to download file from an HTTP URL
https://www.codejava.net/java-se/networking/use-httpurlconnection-to-download-file-from-an-http-url - https://stackoverflow.com/questions/576513/android-download-binary-file-problems
- https://stackoverflow.com/questions/29712554/how-to-download-a-file-using-a-java-rest-service-and-a-data-stream
- HttpClient Download File from URL
https://www.technicalkeeda.com/java-tutorials/httpclient-download-file-from-url - How do I save a file downloaded with HttpClient into a specific folder
https://stackoverflow.com/questions/10960409/how-do-i-save-a-file-downloaded-with-httpclient-into-a-specific-folder - https://stackabuse.com/how-to-download-a-file-from-a-url-in-java/
- https://stackoverflow.com/questions/8324862/how-to-create-file-object-from-url-object
- https://gist.github.com/rponte/09ddc1aa7b9918b52029
=END=