我可以在同一个 REST API 响应中发送一个 excel 文件和 JSON 带有文件描述的正文吗
Can I send an excel file and JSON body with a description of file in same REST API Response
我有一个 API 其中 returns APPLICATION_OCTET_STREAM 作为响应的媒体类型。我需要增强它以发送一个 JSON 正文,其中包含有关文件的一些详细信息,例如文件中正确和错误记录的计数。所以基本上我需要在同一个 API 中进行两种响应。这可行吗?
可以,但您需要使用多部分响应。请记住,某些客户端将无法处理此类响应。您通常会在上传文件时看到这种数据类型,但并不经常用作响应数据类型。
话虽如此,下面是使用 Jersey Test Framework 的完整示例。在资源中,响应中发送了一个文件和一些额外数据,使用 Jersey 的 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
的文件,该文件的第一行包含内容 "Some Test Data in File"(不带引号)。这个多部分响应有两部分,json-data
部分,它使用 Model
class 来模拟 JSON,file-data
部分的内容是文件。
为了使 Multipart 工作,我们需要 MultiPartFeature
在服务器和客户端上注册(用于客户端反序列化),并且我们需要在我们的项目中具有 multipart 依赖项。
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>${jersey2.version}</version>
</dependency>
在客户端,要从响应中获取多部分,我们应该将实体读取为 FormDataMultiPart
,然后我们可以按名称获取各个部分并按其数据类型提取它们。
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");
}
}
要使用测试框架,需要添加如下依赖
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<version>${jersey2.version}</version>
</dependency>
我有一个 API 其中 returns APPLICATION_OCTET_STREAM 作为响应的媒体类型。我需要增强它以发送一个 JSON 正文,其中包含有关文件的一些详细信息,例如文件中正确和错误记录的计数。所以基本上我需要在同一个 API 中进行两种响应。这可行吗?
可以,但您需要使用多部分响应。请记住,某些客户端将无法处理此类响应。您通常会在上传文件时看到这种数据类型,但并不经常用作响应数据类型。
话虽如此,下面是使用 Jersey Test Framework 的完整示例。在资源中,响应中发送了一个文件和一些额外数据,使用 Jersey 的 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
的文件,该文件的第一行包含内容 "Some Test Data in File"(不带引号)。这个多部分响应有两部分,json-data
部分,它使用 Model
class 来模拟 JSON,file-data
部分的内容是文件。
为了使 Multipart 工作,我们需要 MultiPartFeature
在服务器和客户端上注册(用于客户端反序列化),并且我们需要在我们的项目中具有 multipart 依赖项。
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>${jersey2.version}</version>
</dependency>
在客户端,要从响应中获取多部分,我们应该将实体读取为 FormDataMultiPart
,然后我们可以按名称获取各个部分并按其数据类型提取它们。
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");
}
}
要使用测试框架,需要添加如下依赖
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<version>${jersey2.version}</version>
</dependency>