This tutorial will cover how to upload a file with OkHttp, an HTTP & HTTP/2 client for Android and Java applications, powered by Square.
1. Preparation
1.1. REST API for file uploading
Let’s assume that we have a RESTful web service which provides an API for file uploading as below:
1 |
POST http://localhost:8080/v1/upload |
Parameters:
Key | Required | Description |
file | required | A binary file |
name | optional | The name of the file |
1.2. The client side source code
The demo source code can be found on the Github or you can download it here: Java-Examples.zip
We will use the OkHttp 3.4.1 to upload files to the REST API, and the dependency we need is:
1 2 3 4 5 |
<dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>3.4.1</version> </dependency> |
2. Upload a File with OkHttp
In this section, we will illustrate how to make a multipart upload request using OkHttp client library.A multipart upload request allows us to send metadata along with the data to upload.
Let’s see an example code how to upload image to the above REST API:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public class UploadService { private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png"); public void uploadImage(File image, String imageName) throws IOException { OkHttpClient client = new OkHttpClient(); RequestBody requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM) .addFormDataPart("file", imageName, RequestBody.create(MEDIA_TYPE_PNG, image)) .build(); Request request = new Request.Builder().url("http://localhost:8080/v1/upload") .post(requestBody).build(); Response response = client.newCall(request).execute(); if (!response.isSuccessful()) { throw new IOException("Unexpected code " + response); } } } |
There are a few of notices from the source code:
- Firstly we create an instance of the MultipartBody, an RFC 2387-compliant request body, as the body of the request we will issue to the REST API.
- Then we use the addFormDataPart method to add a form data part. The parameters for the method includes the part name, the file name and the binary file.
- Finally, we create the request with the REST URI, the body we have just created and invoke the request.
3. Server side source code
This section describes an example of server side source code implemented for the REST API. The source code is implemented using Spring Boot and can be found on my Github project.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
@RestController @RequestMapping(value = "/v1") public class FileUploadController { @Autowired private StorageService storageService; @RequestMapping(value = "/upload", method = RequestMethod.POST) public ResponseEntity uploadFile(@RequestParam(value = "file") MultipartFile multipartFile) { // stores the file to disk storageService.store(multipartFile); return new ResponseEntity<>("{}", HttpStatus.OK); } } |
The upload method has only one parameter: file and the type is MulipartFile.
4. Conclusion
The tutorial has just presented how to upload a file with OkHttp. We have just performed a multipart upload to the REST API. And we also have seen an example how the server side is implemented. Note that beside the multipart upload, we can use another way to upload a file to a REST API by using Chunked transfer encoding. We will get to know it in another article. Below are other related articles for your references:
Java REST Client Examples Using OkHttp
Basic Authentication with OkHttp Example
WebSocket Client Example with OkHttp
Hello, I tried the above. On the client side, I am using a Java swing application on a Windows machine, with a png file on the desktop. Implemented the server side, basically line for line with what you have above. When I run the server and then try to connect from the swing app, the swing app throws an exception which is a HTTP 405, method not allowed error. Simultaneously as when I get the client error, the server gives the following error: Jan 04, 2017 2:44:59 AM org.springframework.web.servlet.PageNotFound handleHttpRequestMethodNotSupported WARNING: Request method ‘GET’ not supported Why am I getting… Read more »
Hi,
The /home requires POST while you use the GET method. There are 2 possibilities:
1. Use GET method as below example:
Request request = new Request.Builder().url(“http://localhost:8080/v1/home”)
.get().build();
2. Check if you can change the @RequestMapping(value = “/home”, method = RequestMethod.GET)
Hope this help.
Hi, thanks for your response. I had tried those options. By changing to .get().build() and RequestMethod.GET, it then gives a it gets a Unexpected code, Response HTTP 500 Internal Server Error. Just to test, if I keep it as RequestMethod.POST and change it to .get().build(), it gives an HTTP 405 error. Not really sure how to get this example working. Just to double check, in the function prototype: public void uploadImage(File image, String imageName), I am passing the imageName as just the image name string “xxxxx.png” as opposed to the path and filename string. Which one should it be ?… Read more »
Whey you change to .get().build() and RequestMethod.GET and it gives a Unexpected code, Response HTTP 500 Internal Server Error, this means you’re OK with the call. And the problem is your server side code (internal server error). You should check more the stacktrace and figure out the solution to fix. Could you post your stacktrace?
I had also tried okhttp-3.4.1.jar as you listed in section 1.2 and it has the same result.
I found the problem. Instead of:
Request request = new Request.Builder().url(“http://localhost:8080/v1/upload”)
.post(requestBody).build();
It should be:
Request request = new Request.Builder().url(“http://localhost:8080/v1/upload/”)
.post(requestBody).build();
The difference is one forward slash. How ridiculous. See this link for additional reference: https://coderanch.com/t/543593/HTTP-issues-RPC-call
Glad to know that you were able to resolve the issue.
Thanks,