'Upload data file as byte array with Feign
How can I send file in Feign as byte array?
@RequestLine("POST /api/files/{num}/push")
@Headers({"Content-Type: application/zip"})
void pushFile(@Param("num") String num, @Param("file") byte[] file);
This is not working and passing the data in form of json with top element named file. What can I do to properly receive array of bytes on the other side using this controller method parameter annotation?
@RequestBody byte[] file
Solution 1:[1]
You can try OpenFeign/feign-form, simple example:
pom.xml dependencies
<dependencies>
<!--feign dependencies-->
<dependency>
<groupId>io.github.openfeign.form</groupId>
<artifactId>feign-form</artifactId>
<version>3.8.0</version>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId>
<version>10.1.0</version>
</dependency>
<!--jetty to dependencies to check feign request-->
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>9.4.3.v20170317</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>9.4.3.v20170317</version>
</dependency>
</dependencies>
FeignUploadFileExample.java:
import feign.*;
import feign.codec.EncodeException;
import feign.codec.Encoder;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Type;
import java.util.Map;
import static java.nio.charset.StandardCharsets.UTF_8;
public class FeignUploadFileExample {
public static void main(String[] args) throws Exception {
// start jetty server to check feign request
startSimpleJettyServer();
SimpleUploadFileApi simpleUploadFileApi = Feign.builder()
.encoder(new SimpleFileEncoder())
.target(SimpleUploadFileApi.class, "http://localhost:8080/upload");
// upload file bytes (simple string bytes)
byte[] fileBytes = "Hello World".getBytes();
String response = simpleUploadFileApi.uploadFile(fileBytes);
System.out.println(response);
}
public static final String FILE_PARAM = "file";
// encode @Param("file") to request body bytes
public static class SimpleFileEncoder implements Encoder {
public void encode(Object object, Type type, RequestTemplate template)
throws EncodeException {
template.body(Request.Body.encoded(
(byte[]) ((Map) object).get(FILE_PARAM), UTF_8));
}
}
// feign interface to upload file
public interface SimpleUploadFileApi {
@RequestLine("POST /upload")
@Headers("Content-Type: application/zip")
String uploadFile(@Param(FILE_PARAM) byte[] file);
}
// embedded jetty server
public static void startSimpleJettyServer() throws Exception {
Server server = new Server(8080);
ServletContextHandler handler = new ServletContextHandler(server, "/upload");
handler.addServlet(SimpleBlockingServlet.class, "/");
server.start();
}
// simple servlet get request and return info of received data
public static class SimpleBlockingServlet extends HttpServlet {
protected void doPost(
HttpServletRequest request,
HttpServletResponse response) throws IOException {
String data = new BufferedReader(
new InputStreamReader(request.getInputStream())).readLine();
response.setStatus(HttpStatus.OK_200);
response.getWriter().println("Request header 'Content-Type': " +
request.getHeaders("Content-Type").nextElement());
response.getWriter().println("Request downloaded file data: " + data);
}
}
}
response output:
Request header 'Content-Type': application/zip
Request downloaded file data: Hello World
also @RequestBody
it's annotation for REST json body, for files:
@RequestParam("file") MultipartFile file
take a look at Spring Boot Uploading Files
Solution 2:[2]
You can use FormData from feign-form to upload file and specify Content-type
and name
:
<dependency>
<groupId>io.github.openfeign.form</groupId>
<artifactId>feign-form</artifactId>
<version>3.8.0</version>
</dependency>
@RequestLine("POST /api/files/{num}/push")
void pushFile(@Param("num") String num, @Param("file") FormData file);
Usage example:
byte[] bytes = getFileContent();
FormData file = new FormData("application/zip", "example.zip", bytes);
client.pushFile(num, file);
Or in case you are using spring-cloud-starter-openfeign
:
@PostMapping("/api/files/{num}/push")
void pushFile(@PathVariable String num, @RequestPart FormData file);
Tested this for spring-cloud-starter-openfeign
but I assume it works without spring considering FormData
class lives in form-data
dependency.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Joe Taras |
Solution 2 | alaster |