JAVA-从Web服务器下载二进制文件(如PDF)文件

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));

我需要从Web服务器下载一个pdf文件到我的电脑,并在本地保存

我使用Httpclient连接到Web服务器并获取内容正文:

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());