我可以在同一REST API响应中发送Excel文件和JSON正文以及文件说明吗 [英] Can I send an excel file and JSON body with a description of file in same REST API Response
问题描述
我有一个API,作为响应,该API返回APPLICATION_OCTET_STREAM作为媒体类型.我需要对其进行增强,以发送包含有关该文件的一些详细信息的JSON正文,例如文件中对和错记录的计数.因此,基本上我需要在同一API中提供两种响应.这可行吗?
I have an API which returns APPLICATION_OCTET_STREAM as Media Type in response. I need to enhance it to also send a JSON body with some details regarding the file, say counts of right and wrong records in the file. So basically I need two kinds of response in same API. Is this doable ?
推荐答案
可以,但是您需要使用Multipart响应.请记住,尽管某些客户端将无法处理这种类型的响应.通常,您会在上传文件时看到此数据类型,但很少将其用作响应数据类型.
It's possible, but you will need to use a Multipart response. Keep in mind though that some clients will not be able to handle this type of response. You'll normally see this data type using in uploading files, but is not very often used as a response data type.
话虽如此,下面是使用 Jersey测试框架的完整示例.在资源中,使用Jersey的FormDataMultiPart
That being said, below is a complete example using the Jersey Test Framework. In the resource, a file and some extra data are being sent in the response, with the use of Jersey's FormDataMultiPart
@Path("test")
public static class TestResource {
@GET
@Produces(MediaType.MULTIPART_FORM_DATA)
public Response get() throws Exception {
final MultiPart multiPart = new FormDataMultiPart()
.field("json-data", new Model("Test Value"), MediaType.APPLICATION_JSON_TYPE)
.bodyPart(new FileDataBodyPart("file-data", new File("test.txt")));
return Response.ok(multiPart).build();
}
}
要使测试成功,您应该在文件的第一行上有一个名为test.txt
的文件,其内容为文件中有一些测试数据"(不带引号).这个多部分响应包括两个部分:json-data
部分和file-data
部分,其中json-data
部分使用Model
类对JSON进行建模,而file-data
部分具有文件的内容.
To make the test succeed, you should have a file called test.txt
with the content "Some Test Data in File" (without quotes) on the first line of that file. This multipart response has two parts, the json-data
part, which uses a Model
class to model the JSON, and the file-data
part which has the contents of the file.
要使Multipart正常工作,我们需要在服务器和客户端上进行MultiPartFeature
注册(用于客户端反序列化),并且需要在项目中具有multipart依赖项.
To make the Multipart work, we need to have the MultiPartFeature
register on the server and the client (for client side deserialization) and we need to have the multipart dependency in our project.
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>${jersey2.version}</version>
</dependency>
在客户端上,要从响应中获取多部分,我们应将实体读取为FormDataMultiPart
,然后我们可以按名称获取各个部分并按其数据类型提取它们.
On the client, to get the multipart out of the response, we should read the entity as FormDataMultiPart
, then we can get individual parts by name and extract them by their data type.
Response res = target("test").request().get();
FormDataMultiPart multiPart = res.readEntity(FormDataMultiPart.class);
FormDataBodyPart jsonPart = multiPart.getField("json-data");
FormDataBodyPart filePart = multiPart.getField("file-data");
Model jsonData = jsonPart.getValueAs(Model.class);
InputStream file = filePart.getValueAs(InputStream.class);
下面是完整的测试.
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.media.multipart.FormDataBodyPart;
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
import org.glassfish.jersey.media.multipart.MultiPart;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.media.multipart.file.FileDataBodyPart;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Test;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import static org.assertj.core.api.Assertions.assertThat;
public class MultipartResponseTest extends JerseyTest {
public static class Model {
private String value;
public Model() {}
public Model(String value) {
this.value = value;
}
public String getValue() {
return this.value;
}
public void setValue(String value) {
this.value = value;
}
}
@Path("test")
public static class TestResource {
@GET
@Produces(MediaType.MULTIPART_FORM_DATA)
public Response get() throws Exception {
final MultiPart multiPart = new FormDataMultiPart()
.field("json-data", new Model("Test Value"), MediaType.APPLICATION_JSON_TYPE)
.bodyPart(new FileDataBodyPart("file-data", new File("test.txt")));
return Response.ok(multiPart).build();
}
}
@Override
public ResourceConfig configure() {
return new ResourceConfig()
.register(TestResource.class)
.register(MultiPartFeature.class);
}
@Override
public void configureClient(ClientConfig config) {
config.register(MultiPartFeature.class);
}
@Test
public void testIt() throws Exception {
final Response res = target("test")
.request().get();
FormDataMultiPart multiPart = res.readEntity(FormDataMultiPart.class);
FormDataBodyPart jsonPart = multiPart.getField("json-data");
FormDataBodyPart filePart = multiPart.getField("file-data");
Model jsonData = jsonPart.getValueAs(Model.class);
InputStream file = filePart.getValueAs(InputStream.class);
BufferedReader fileReader = new BufferedReader(new InputStreamReader(file));
String fileData = fileReader.readLine();
file.close();
fileReader.close();
System.out.println(jsonData.getValue());
System.out.println(fileData);
assertThat(jsonData.getValue()).isEqualTo("Test Value");
assertThat(fileData).isEqualTo("Some Test Data in File");
}
}
要使用测试框架,您应该添加以下依赖项
To use the test framework, you should add the following dependency
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<version>${jersey2.version}</version>
</dependency>
这篇关于我可以在同一REST API响应中发送Excel文件和JSON正文以及文件说明吗的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!