JAVA-从Web服务器下载二进制文件(如PDF)文件
我需要从Web服务器下载一个pdf文件到我的电脑,并在本地保存 我使用Httpclient连接到Web服务器并获取内容正文:JAVA-从Web服务器下载二进制文件(如PDF)文件,java,post,login,httpclient,Java,Post,Login,Httpclient,我需要从Web服务器下载一个pdf文件到我的电脑,并在本地保存 我使用Httpclient连接到Web服务器并获取内容正文: HttpEntity entity=response.getEntity(); InputStream in=entity.getContent(); String stream = CharStreams.toString(new InputStreamReader(in));
HttpEntity entity=response.getEntity();
InputStream in=entity.getContent();
String stream = CharStreams.toString(new InputStreamReader(in));
int size=stream.length();
System.out.println("stringa html page LENGTH:"+stream.length());
System.out.println(stream);
SaveToFile(stream);
然后我将内容保存在一个文件中:
//check CRLF (i don't know if i need to to this)
String[] fix=stream.split("\r\n");
File file=new File("C:\\Users\\augusto\\Desktop\\progetti web\\test\\test2.pdf");
PrintWriter out = new PrintWriter(new FileWriter(file));
for (int i = 0; i < fix.length; i++) {
out.print(fix[i]);
out.print("\n");
}
out.close();
但结果总是一样的:我可以打开pdf文件,但只能看到白页。错误是否与pdf流和endstream字符集编码有关?流和端流之间的pdf内容是否需要以其他方式进行操作
希望这有助于避免对我想做的事情产生误解: 这是我的登录(工作正常): 响应主体示例:
%PDF-1.7
1 0 obj % entry point
<<
/Type /Catalog
/Pages 2 0 R
如果您想要更有效的方法,可以使用java.IOUtils并执行以下操作:
public void saveFile(InputStream is){
try {
DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(new File("test.pdf"))));
int c;
while((c = is.read()) != -1) {
out.writeByte(c);
}
out.close();
is.close();
}catch(IOException e) {
System.err.println("Error Writing/Reading Streams.");
}
}
public void saveFile(InputStream is){
OutputStream os=new FileOutputStream(new File("test.pdf"));
byte[] bytes = IOUtils.toByteArray(is);
os.write(bytes);
os.close();
}
从不将二进制数据存储到字符串中
绝不对二进制数据使用PrintWriter
决不逐行写入二进制文件
我不想太苛刻或不礼貌,但这三点永远不必在你的脑海中扎根
您可以查看有关如何下载二进制文件的示例。我不喜欢这个示例,因为它将整个文档缓存在内存中(如果大小为5GB会发生什么情况?),但您可以从以下内容开始:) 你就不能接受链接吗
public static void downloadFile(URL from, File to, boolean overwrite) throws Exception {
if (to.exists()) {
if (!overwrite)
throw new Exception("File " + to.getAbsolutePath() + " exists already.");
if (!to.delete())
throw new Exception("Cannot delete the file " + to.getAbsolutePath() + ".");
}
int lengthTotal = 0;
try {
HttpURLConnection content = (HttpURLConnection) from.openConnection();
lengthTotal = content.getContentLength();
} catch (Exception e) {
lengthTotal = -1;
}
int lengthSoFar = 0;
InputStream is = from.openStream();
FileOutputStream fos = new FileOutputStream(to);
int lastUpdate = 0;
int c;
while ((c = is.read()) != -1) {
fos.write(c);
}
is.close();
fos.close();
}
使用apachefileutils。我用一个小PDF和一个60兆的罐子试了一下。很好
import java.io.File;
import java.io.IOException;
import java.net.URL;
import org.apache.commons.io.FileUtils;
String uri = "http://localhost:8080/PMInstaller/f1.pdf";
URL url = new URL(uri);
File destination = new File("f1.pdf");
FileUtils.copyURLToFile(url, destination);
让我们来完成下载响应为字节的艰苦工作
Response response= Jsoup.connect(location)
.ignoreContentType(true)
.userAgent("Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0")
.referrer("http://www.google.com")
.timeout(12000)
.execute();
使用FileUtil写入字节
FileUtils.writeByteArrayToFile(new File(path), response.bodyAsBytes());
逐字节读取是疯狂的。但是+1,因为总体意图是好的。你是对的。。。这是为小文件开发的,并且有一个精确的进度条。不管你信不信由你,我最近把它与nio下载文件的速度进行了比较,在nio中,你只需连接两个流,它需要相同的时间……是的,网络可能比我们编写的任何未优化的代码都“糟糕”。我们的机器越来越好,而我们的网络越来越差。你应该在一个100Mbit的局域网上用一个5GB的文档试试,它最终会有所不同……Hurledown,我必须先用一系列cookies登录到Web服务器,然后我才能下载文件。有什么建议吗?你正在编程一个HTTP机器人。这需要一些努力,因为没有一行提示。对于cookies:要登录,您可能需要在登录页面上发布凭据。请参阅:“更高效”方法的可能副本是垃圾,因为它将整个文件存储在内存中!使用2 GB的文件进行尝试:)。。。代码更少!=效率更高。不过,我很高兴你解决了你的问题!!干得好gd1,谢谢你的评论。“它将整个文件存储在内存中!”,是的,这是真的。但这取决于应用程序。在本例中,我们讨论的是电子邮件附件,附件大小超过10 MB的情况很少见。:)不过我很感谢你的建议,再次感谢你!:)我试过你的例子(几天前我已经试过了),但是娜达。在这种情况下,pdf文件不会打开。你不应该试图复制和粘贴其他人编写的代码片段,希望你随机找到正确的组合。一旦您理解了这个问题(下载二进制文件,而不是文本文件),您就应该使用Java文档中的示例,以便找到一个既正确又适合您需要的解决方案,但不管您是如何编写的。逐行编写一些代码,调试每一行,并为我们创建一个SSCE(),因此不要在您的程序中尝试您在Internet上找到的示例和hurtledown提供的示例,而是在一个适当的、单独的测试用例中,真正向我们展示它在何处以及如何失败。此外,请了解Java字节流,因为如果您发现可以逐行编写二进制文件,那么即使您成功地使程序以某种笨拙的方式工作,您也会遇到越来越多的问题。把事情搞定!显然,我根据自己的代码改编了示例代码,我不是超级傻瓜!!!…)我已经使用urlConnection库(如hartleMan示例)测试了其他脚本,以便在其他不需要登录的Web服务器上下载其他pdf文件,一切正常。(pdf已成功打开)我会在一个单独的测试用例中尝试您和hartleman的例子,但我不能,因为要复制真正的测试,我需要首先登录到特定的Web服务器,然后下载pdf文件。但是用UrlConnection管理cookie太难了!好啊所以这个问题不能在这里解决,因为我们不知道你的代码在登录部分会弄乱什么,而且“我试过你的例子(我几天前已经试过了),但是nada”至少是误导性的,你不觉得吗?您不需要S.O.,基本上必须调试代码。如果你的登录部分不起作用,那么停止告诉你有一个下载PDF的问题,集中精力。但是,如果你一直认为使用PrintWriter可以,那么显然你也有下载PDF的问题。:)
public void saveFile(InputStream is){
OutputStream os=new FileOutputStream(new File("test.pdf"));
byte[] bytes = IOUtils.toByteArray(is);
os.write(bytes);
os.close();
}
public static void downloadFile(URL from, File to, boolean overwrite) throws Exception {
if (to.exists()) {
if (!overwrite)
throw new Exception("File " + to.getAbsolutePath() + " exists already.");
if (!to.delete())
throw new Exception("Cannot delete the file " + to.getAbsolutePath() + ".");
}
int lengthTotal = 0;
try {
HttpURLConnection content = (HttpURLConnection) from.openConnection();
lengthTotal = content.getContentLength();
} catch (Exception e) {
lengthTotal = -1;
}
int lengthSoFar = 0;
InputStream is = from.openStream();
FileOutputStream fos = new FileOutputStream(to);
int lastUpdate = 0;
int c;
while ((c = is.read()) != -1) {
fos.write(c);
}
is.close();
fos.close();
}
import java.io.File;
import java.io.IOException;
import java.net.URL;
import org.apache.commons.io.FileUtils;
String uri = "http://localhost:8080/PMInstaller/f1.pdf";
URL url = new URL(uri);
File destination = new File("f1.pdf");
FileUtils.copyURLToFile(url, destination);
Response response= Jsoup.connect(location)
.ignoreContentType(true)
.userAgent("Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0")
.referrer("http://www.google.com")
.timeout(12000)
.execute();
FileUtils.writeByteArrayToFile(new File(path), response.bodyAsBytes());