Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for Http Client API in Java: Managing Files
Noe Lopez
Noe Lopez

Posted on • Edited on

     

Http Client API in Java: Managing Files

Overview

The purpose of this article is to show how to use the Http Client API to upload/download file contents from a REST endpoint.

Let's recap the steps to make a call to a web resource as this process is the same to upload/download file data.

  • HttpClient object is created and configured further if needed (timeout, authenticator, http version, followRedirects...)

  • Http Request is created passing the URL. Optionally, other features can be set. For instance, http method, http headers, timeout and http version.

  • Then, the HttpResponse is not created directly, but rather returned as a result of sending an HttpRequest with the HttpClient. Once it is completed, the status code and body if any can be inspected from it.

Now, let's continue with the download file use case.

Downloading file contents

We will follow the steps described above to perform this operation. But first, let's look at the backend. The endpoint is sending back the contents of the files as a byte array

@RestController@RequestMapping("api/v1/documents")publicclassDocumentController{// ommited code here@GetMapping(value="/{documentId}")ResponseEntity<Resource>downloadDocument(@PathVariableLongdocumentId){Optional<Document>document=documentRepo.findById(documentId);if(document.isEmpty())returnResponseEntity.notFound().build();returnResponseEntity.ok().contentType(MediaType.parseMediaType(document.get().getType())).header(HttpHeaders.CONTENT_DISPOSITION,"attachment;                 filename=\""+document.get().getName()+"\"").body(newByteArrayResource(document.get().getContents()));}
Enter fullscreen modeExit fullscreen mode

The API provides the BodyHandlers class (HttpResponse inner static class) to manage common response types such as String or File. Below is a list of some useful methods available in this class:

  1. ofByteArray: the body is written to byte array.
  2. ofFile: the body is written to the file, and HttpResponse.body() returns a reference to its Path.
  3. ofFileDownload: the body is completely written to the file and HttpResponse.body() returns a Path object for the file.
  4. ofString: The body is writen to string and decoded using the character set specified in the Content-Type response header.
  5. ofInputStream: returns an InputStream from which the body can be read as it is received.
  6. ofLines: returns an Stream. The body may have not been received yet.
  7. ofPublisher: returns a Publisher from which the body response bytes can be obtained as they are received. The publisher can and must be subscribed to only once.

As the endpoint returns a byte array, the ofByteArray method seems to be a good match. The filename is extracted from the Content-Disposition header. Code snippet shown beneath:

// Byte ArrayHttpResponse<byte[]>response=client.send(request,HttpResponse.BodyHandlers.ofByteArray());StringheaderContentDisposition=(String)response.headers().firstValue("content-     disposition").get();StringfileName="C:/workspace/files/"+getFileName(headerContentDisposition);// Save to fileFiles.write(Paths.get(fileName),response.body(),StandardOpenOption.CREATE_NEW);
Enter fullscreen modeExit fullscreen mode

When the program is executed the file is successfully dowloaded to the location specified.

Directory: C:\workspace\filesMode            LastWriteTime         Length Name                                                                                                                                 ----            -------------         ------ ----                                                                                                                                 -a----          4/1/2023   7:28 PM    388374 LinuxCommands.jpg
Enter fullscreen modeExit fullscreen mode

It is possible to use a different BodyHandler to download the file as proved in the following lines

HttpResponse<Path>response=client.send(request,HttpResponse.BodyHandlers.ofFile(Path.of("C:/workspace/files/DownloadedFile.jpg")));
Enter fullscreen modeExit fullscreen mode

Another option is to use the ofInputStream method.

HttpResponse<InputStream>response=client.send(request,HttpResponse.BodyHandlers.ofInputStream());StringheaderContentDisposition=(String)response.headers().firstValue("content-    disposition").get();StringfileName="C:/workspace/files/"+getFileName(headerContentDisposition);Files.copy(response.body(),Paths.get(fileName),StandardCopyOption.REPLACE_EXISTING);
Enter fullscreen modeExit fullscreen mode

As you can see there are plenty of choices to get the job done :-).

Uploading file contents

In this user case, two different endpoints to upload a file have been setup. Hence, we will see different ways to send the body in action.
Request bodies are provided through a BodyPublisher supplied to one of the POST or PUT methods. The class BodyPublishers provides implementations of many common publishers. Here is a list of some of the methods available in BodyPublishers

  1. ofString: returns a BodyPublisher whose body is the given String, converted using the UTF_8 character.
  2. ofInputStream: A body publisher that reads its data from an InputStream.
  3. ofByteArray: Returns a request body publisher whose body is the given byte array.
  4. ofFile: A request body publisher that takes data from the contents of a File.
  5. ofByteArrays: A request body publisher that takes data from an Iterable of byte arrays.

Now we can move on to the first upload example. The rest endpoint is expecting the file contents as a String. The file type and name are coming in headers.

@PostMapping()ResponseEntity<Void>uploadDocument(@RequestBodyStringdata,@RequestHeader("Content-Type")Stringtype,@RequestHeader("fileName")StringfileName){Documentdocument=newDocument();document.setName(fileName);document.setCreationDate(LocalDate.now());document.setType(type);document.setContents(data.getBytes());documentRepo.save(document);returnResponseEntity.created(URI.create("http://localhost:8080/api/v1/documents/"+document.getId())).build();}
Enter fullscreen modeExit fullscreen mode

As you can see the BodyPublishers.ofFile method takes a Path as a parameter. When the request is sent the body will contain the contents of the file.

Pathfile=Paths.get("C:/workspace/files/trees.jpg");varrequest=HttpRequest.newBuilder().uri(URI.create("http://localhost:8080/api/v1/documents")).header("Content-Type","image/jpg").header("fileName",file.getFileName().toString()).header("Authorization",getBasicAuthenticationHeader("admin1234","password5678")).POST(HttpRequest.BodyPublishers.ofFile(file)).build();HttpResponse<String>response=client.send(request,HttpResponse.BodyHandlers.ofString());System.out.printf("Status %s \n",response.statusCode());System.out.printf("Headers %s \n",response.headers().firstValue("location"));
Enter fullscreen modeExit fullscreen mode

Output

Status 201 Headers Optional[http://localhost:8080/api/v1/documents/3]
Enter fullscreen modeExit fullscreen mode

File is saved to the database and URL to find it is return in the location header.
In the second example the controller takes the body as a byte array.

@RestController@RequestMapping("api/v2/documents")publicclassDocumentControllerV2{@PostMapping()ResponseEntity<Void>uploadDocument(@RequestBodybyte[]data,@RequestHeader("Content-Type")Stringtype,@RequestHeader("fileName")StringfileName){// omitted code}}
Enter fullscreen modeExit fullscreen mode

The method ofByteArray is the perfect match in this situation. All that is needed is to convert the contents of the file into a byte array. For that to happen the FileInputStream will do the work.

StringfileName="C:/workspace/files/java_tutorial.pdf";varrequest=HttpRequest.newBuilder().uri(URI.create("http://localhost:8080/api/v2/documents")).header("Content-Type","image/png").header("filename",fileName.substring(fileName.lastIndexOf("/"))).POST(HttpRequest.BodyPublishers.ofByteArray(newFileInputStream(fileName).readAllBytes())).build();varresponse=client.send(request,HttpResponse.BodyHandlers.ofString());System.out.printf("Status %s \n",response.statusCode());System.out.printf("Headers %s \n",response.headers().firstValue("location"));
Enter fullscreen modeExit fullscreen mode

Output

Status 201 Headers Optional[http://localhost:8080/api/v1/documents/4]
Enter fullscreen modeExit fullscreen mode

Finnaly, to verify that the new files are stored in the database, the list files endpoint is called.

[{"name":"PlainText.txt","creationDate":"2023-03-15","size":26,"type":"text/plain"},{"name":"LinuxCommands.jpg","creationDate":"2023-02-07","size":388374,"type":"image/jpeg"},{"name":"trees.jpg","creationDate":"2023-04-02","size":21011905,"type":"image/jpg"},{"name":"/java_tutorial.pdf","creationDate":"2023-04-02","size":1012786,"type":"image/png"}
Enter fullscreen modeExit fullscreen mode

Summary

So that's it. Downloading and uploading files using Java's core API is quite simple. We have to pick a suitable body publisher or body handler to send the file contents and receive the file contents respectively.

This was the last article of this mini series in which we have looked at the Java Http Client API. Previous artices can be found in the below links:

  1. Introduction to the API plus most common use cases.

  2. Sending Security Credentials to Authenticate

Hope you have enjoyed the read! Nore Java related article to come in the future.

Check the code onGitHub

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Java | Spring | Javascript
  • Location
    Curitiba, Brazil
  • Education
    Maths at UAM (Universidad Autonoma De Madrid)
  • Work
    Java Developer at Version1
  • Joined

More fromNoe Lopez

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp