44

I am trying to download a PDF file with HttpClient. I am able to get the file but i am not sure how to convert the bytes into a a PDF and store it somewhere on the system

I have the following code, How can I store it as a PDF?

 public ???? getFile(String url) throws ClientProtocolException, IOException{

            HttpGet httpget = new HttpGet(url);
            HttpResponse response = httpClient.execute(httpget);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                long len = entity.getContentLength();
                InputStream inputStream = entity.getContent();
                // How do I write it?
            }

            return null;
        }
nhahtdh
  • 55,989
  • 15
  • 126
  • 162
124697
  • 22,097
  • 68
  • 188
  • 315

7 Answers7

49
InputStream is = entity.getContent();
String filePath = "sample.txt";
FileOutputStream fos = new FileOutputStream(new File(filePath));
int inByte;
while((inByte = is.read()) != -1)
     fos.write(inByte);
is.close();
fos.close();

EDIT:

you can also use BufferedOutputStream and BufferedInputStream for faster download:

BufferedInputStream bis = new BufferedInputStream(entity.getContent());
String filePath = "sample.txt";
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(filePath)));
int inByte;
while((inByte = bis.read()) != -1) bos.write(inByte);
bis.close();
bos.close();
Aaron
  • 1,390
  • 1
  • 16
  • 30
Eng.Fouad
  • 115,165
  • 71
  • 313
  • 417
  • 9
    HttpClient optimizes read operations internally. There is no need to use another buffering layer – ok2c Aug 18 '15 at 07:25
  • I couldn't write directly to that file path, I had to use `File file = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),"filename.jpg");` for writing to external storage so other apps could see my app – Aaron Sep 25 '15 at 15:08
47

Just for the record there are better (easier) ways of doing the same

File myFile = new File("mystuff.bin");

CloseableHttpClient client = HttpClients.createDefault();
try (CloseableHttpResponse response = client.execute(new HttpGet("http://host/stuff"))) {
    HttpEntity entity = response.getEntity();
    if (entity != null) {
        try (FileOutputStream outstream = new FileOutputStream(myFile)) {
            entity.writeTo(outstream);
        }
    }
}

Or with the fluent API if one likes it better

Request.Get("http://host/stuff").execute().saveContent(myFile);
ok2c
  • 26,450
  • 5
  • 63
  • 71
  • 3
    Witch package do i need to import for `Request.Get("http://host/stuff").execute().saveContent(myFile)` – badera Jun 16 '16 at 19:26
  • 3
    In Maven you need the artifact `org.apache.httpcomponents:fluent-hc` - the Java package is `org.apache.http.client.fluent.Request` – Martin Röbert Jul 05 '17 at 13:43
25

Here is a simple solution using IOUtils.copy():

File targetFile = new File("foo.pdf");

if (entity != null) {
    InputStream inputStream = entity.getContent();
    OutputStream outputStream = new FileOutputStream(targetFile);
    IOUtils.copy(inputStream, outputStream);
    outputStream.close();
}

return targetFile;

IOUtils.copy() is great because it handles buffering. However this solution is not very scalable:

  • you cannot specify target file name and directory
  • you might wish to store the files in a different way, e.g. in a database. Files aren't needed in this scenario.

Much more scalable solution involves two functions:

public void downloadFile(String url, OutputStream target) throws ClientProtocolException, IOException{
    //...
    if (entity != null) {
    //...
        InputStream inputStream = entity.getContent();
        IOUtils.copy(inputStream, target);
    }
}

And a helper method:

public void downloadAndSaveToFile(String url, File targetFile) {
    OutputStream outputStream = new FileOutputStream(targetFile);
    downloadFile(url, outputStream);
    outputStream.close();
}
Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
5

Using dependency org.apache.httpcomponents:fluent-hc:

Request.Get(url).execute().saveContent(file);

Request is from org.apache.http.client.fluent.Request.

In my case I needed a stream, this is equally simple:

inputStream = Request.Get(url).execute().returnContent().asStream();
Aleris
  • 7,981
  • 3
  • 36
  • 42
3

If you are using Java 7+, you can use the native Files.copy(InputStream in, Path target, CopyOption... options), e.g.:

HttpEntity entity = response.getEntity();

try (InputStream inputStream = entity.getContent()) {
    Files.copy(inputStream, Paths.get(filePathString), StandardCopyOption.REPLACE_EXISTING);
}
dlauzon
  • 1,241
  • 16
  • 23
1

Open a FileOutputStream and save the bytes from inputStream to it.

nhahtdh
  • 55,989
  • 15
  • 126
  • 162
Jeffrey Zhao
  • 4,923
  • 4
  • 30
  • 52
  • What's confusing me is that you have a FileOutputStream already open in the downloadAndSaveToFile method, but when I create the File object with the full path, I get a 'File does not exist' error ... can you show us code that would take this file which was downloaded and save it to a specific folder? – Michael Sims Feb 17 '17 at 01:35
  • I apologize, I had a typo in my path. As it turns out, I can specify the file object with full desired path when the path is a VALID path. :-) – Michael Sims Feb 17 '17 at 03:29
0

You can also use Apache http client fluent API

Executor executor = Executor.newInstance().auth(new HttpHost(host), "user", "password"); 
executor.execute(Request.Get(url.toURI()).connectTimeout(1000)).saveContent("C:/temp/somefile");
Anand
  • 1,845
  • 2
  • 20
  • 25