我想通过上传图片和员工数据来在系统中创建员工信息。我能够使用球衣进行不同的休息呼叫。但我希望在一次休息电话中实现。 我提供下面的结构。请帮我在这方面做些什么。
@POST
@Path("/upload2")
@Consumes({MediaType.MULTIPART_FORM_DATA,MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response uploadFileWithData(
@FormDataParam("file") InputStream fileInputStream,
@FormDataParam("file") FormDataContentDisposition contentDispositionHeader,
Employee emp) {
//..... business login
}
每当我想要做的时候,我都会在Chrome邮递员中出错。我的Employee json的简单结构如下所示。
{
"Name": "John",
"Age": 23,
"Email": "john@gmail.com",
"Adrs": {
"DoorNo": "12-A",
"Street": "Street-11",
"City": "Bangalore",
"Country": "Karnataka"
}
}
但是我可以通过进行两次不同的调用来实现,但我希望在一次休息调用中实现,以便我可以接收文件以及员工的实际数据。
请求您在这方面提供帮助。
答案 0 :(得分:83)
你不能有两个Content-Type
(从技术上来说,这就是我们在下面所做的,但是它们与多部分的每个部分分开,但主要类型是多部分)。这基本上是你对你的方法所期望的。您期望将mutlipart 和 json一起作为主要媒体类型。 Employee
数据需要是多部分的一部分。因此,您可以为@FormDataParam("emp")
添加Employee
。
@FormDataParam("emp") Employee emp) { ...
这是我用于测试的课程
@Path("/multipart")
public class MultipartResource {
@POST
@Path("/upload2")
@Consumes({MediaType.MULTIPART_FORM_DATA})
public Response uploadFileWithData(
@FormDataParam("file") InputStream fileInputStream,
@FormDataParam("file") FormDataContentDisposition cdh,
@FormDataParam("emp") Employee emp) throws Exception{
Image img = ImageIO.read(fileInputStream);
JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(img)));
System.out.println(cdh.getName());
System.out.println(emp);
return Response.ok("Cool Tools!").build();
}
}
首先,我刚刚使用客户端API进行了测试,以确保其正常工作
@Test
public void testGetIt() throws Exception {
final Client client = ClientBuilder.newBuilder()
.register(MultiPartFeature.class)
.build();
WebTarget t = client.target(Main.BASE_URI).path("multipart").path("upload2");
FileDataBodyPart filePart = new FileDataBodyPart("file",
new File("stackoverflow.png"));
// UPDATE: just tested again, and the below code is not needed.
// It's redundant. Using the FileDataBodyPart already sets the
// Content-Disposition information
filePart.setContentDisposition(
FormDataContentDisposition.name("file")
.fileName("stackoverflow.png").build());
String empPartJson
= "{"
+ " \"id\": 1234,"
+ " \"name\": \"Peeskillet\""
+ "}";
MultiPart multipartEntity = new FormDataMultiPart()
.field("emp", empPartJson, MediaType.APPLICATION_JSON_TYPE)
.bodyPart(filePart);
Response response = t.request().post(
Entity.entity(multipartEntity, multipartEntity.getMediaType()));
System.out.println(response.getStatus());
System.out.println(response.readEntity(String.class));
response.close();
}
我刚创建了一个简单的Employee
类,其中包含id
和name
字段供测试。这完全没问题。它显示图像,打印内容配置,并打印Employee
对象。
我对Postman不太熟悉,所以我保存了最后的测试: - )
它似乎也可以正常工作,因为您可以看到响应"Cool Tools"
。但是,如果我们查看打印的Employee
数据,我们会看到它是空的。这很奇怪,因为客户端API工作正常。
如果我们查看预览窗口,我们会看到问题
Content-Type
正文部分没有emp
标头。您可以在客户端API中看到我明确设置它
MultiPart multipartEntity = new FormDataMultiPart()
.field("emp", empPartJson, MediaType.APPLICATION_JSON_TYPE)
.bodyPart(filePart);
所以我猜这只是部分的完整答案。就像我说的那样,我对Postman并不熟悉因此我不知道如何为个体部位设置Content-Type
s。我为图像部分自动设置了图像的image/png
(我猜它只是由文件扩展名决定)。如果你能解决这个问题,那么问题就应该解决了。如果您发现如何操作,请将其作为答案发布。
基本配置:
相关性:
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>${jersey2.version}</version>
</dependency>
客户端配置:
final Client client = ClientBuilder.newBuilder()
.register(MultiPartFeature.class)
.build();
服务器配置:
// Create JAX-RS application.
final Application application = new ResourceConfig()
.packages("org.glassfish.jersey.examples.multipart")
.register(MultiPartFeature.class);
从Postman客户端可以看出,使用FormData
(js)时,一些客户端无法设置单个部件的Content-Type,包括浏览器的默认功能。
我们不能指望客户找到这个,所以我们可以做的是,在接收数据时,在反序列化之前显式设置Content-Type。例如
@POST
@Path("upload2")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFileAndJSON(@FormDataParam("emp") FormDataBodyPart jsonPart,
@FormDataParam("file") FormDataBodyPart bodyPart) {
jsonPart.setMediaType(MediaType.APPLICATION_JSON_TYPE);
Employee emp = jsonPart.getValueAs(Employee.class);
}
获得POJO需要额外的工作,但这比强迫客户尝试找到自己的解决方案更好。
答案 1 :(得分:2)
您可以使用MULTIPART FORM DATA从表格访问图像文件和数据使用以下代码。
@POST
@Path("/UpdateProfile")
@Consumes(value={MediaType.APPLICATION_JSON,MediaType.MULTIPART_FORM_DATA})
@Produces(value={MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
public Response updateProfile(
@FormDataParam("file") InputStream fileInputStream,
@FormDataParam("file") FormDataContentDisposition contentDispositionHeader,
@FormDataParam("ProfileInfo") String ProfileInfo,
@FormDataParam("registrationId") String registrationId) {
String filePath= "/filepath/"+contentDispositionHeader.getFileName();
OutputStream outputStream = null;
try {
int read = 0;
byte[] bytes = new byte[1024];
outputStream = new FileOutputStream(new File(filePath));
while ((read = fileInputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, read);
}
outputStream.flush();
outputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch(Exception ex) {}
}
}
}
答案 2 :(得分:0)
您的ApplicationConfig应该注册glassfish.jersey.media中的MultiPartFeature.class ..以便启用文件上传
@javax.ws.rs.ApplicationPath(ResourcePath.API_ROOT)
public class ApplicationConfig extends ResourceConfig {
public ApplicationConfig() {
//register the necessary headers files needed from client
register(CORSConfigurationFilter.class);
//The jackson feature and provider is used for object serialization
//between client and server objects in to a json
register(JacksonFeature.class);
register(JacksonProvider.class);
//Glassfish multipart file uploader feature
register(MultiPartFeature.class);
//inject and registered all resources class using the package
//not to be tempered with
packages("com.flexisaf.safhrms.client.resources");
register(RESTRequestFilter.class);
}
答案 3 :(得分:0)
我想在peeskillet上添加评论,但不要有50个声望点,因此添加一个答案:
当我使用Jersey客户端2.21.1尝试@peeskillet解决方案时,出现了400错误。当我在我的客户端代码中添加以下内容时,它工作正常:
MediaType contentType = MediaType.MULTIPART_FORM_DATA_TYPE;
contentType = Boundary.addBoundary(contentType);
Response response = t.request().post(
Entity.entity(multipartEntity, contentType));
而不是在请求后调用中硬编码的MediaType.MULTIPART_FORM_DATA。
答案 4 :(得分:0)
请求类型是multipart / form-data,您要发送的本质上是形式为字段的字节形式的字段,内容边界将不同的形式字段分隔开来。来自客户端的序列化表格,然后可以在服务器上反序列化。
毕竟,实际上没有编程环境对象在线路上运行。双方的编程环境都在执行自动序列化和反序列化,您也可以这样做。这是最干净且编程环境怪异的免费方法。
作为示例,这是一个发布到Jersey示例服务的javascript客户端,
submitFile(){
let data = new FormData();
let account = {
"name": "test account",
"location": "Bangalore"
}
data.append('file', this.file);
data.append("accountKey", "44c85e59-afed-4fb2-884d-b3d85b051c44");
data.append("device", "test001");
data.append("account", JSON.stringify(account));
let url = "http://localhost:9090/sensordb/test/file/multipart/upload";
let config = {
headers: {
'Content-Type': 'multipart/form-data'
}
}
axios.post(url, data, config).then(function(data){
console.log('SUCCESS!!');
console.log(data.data);
}).catch(function(){
console.log('FAILURE!!');
});
},
客户端在这里发送一个文件,2个表单字段(字符串)和一个已经过字符串传输的帐户对象。这是表单域在网上的外观,
在服务器上,您可以按照自己认为合适的方式反序列化表单字段。为了完成这个简单的例子,
@POST
@Path("/file/multipart/upload")
@Consumes({MediaType.MULTIPART_FORM_DATA})
public Response uploadMultiPart(@Context ContainerRequestContext requestContext,
@FormDataParam("file") InputStream fileInputStream,
@FormDataParam("file") FormDataContentDisposition cdh,
@FormDataParam("accountKey") String accountKey,
@FormDataParam("account") String json) {
System.out.println(cdh.getFileName());
System.out.println(cdh.getName());
System.out.println(accountKey);
try {
Account account = Account.deserialize(json);
System.out.println(account.getLocation());
System.out.println(account.getName());
} catch (Exception e) {
e.printStackTrace();
}
return Response.ok().build();
}
答案 5 :(得分:-2)
我使用了文件上传示例,
http://www.mkyong.com/webservices/jax-rs/file-upload-example-in-jersey/
在我的资源类中我有以下方法
@POST
@Path("/upload")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response attachupload(@FormDataParam("file") byte[] is,
@FormDataParam("file") FormDataContentDisposition fileDetail,
@FormDataParam("fileName") String flename){
attachService.saveAttachment(flename,is);
}
在我的attachService.java中我有以下方法
public void saveAttachment(String flename, byte[] is) {
// TODO Auto-generated method stub
attachmentDao.saveAttachment(flename,is);
}
在道我有
attach.setData(is);
attach.setFileName(flename);
我的HBM映射中的就像
<property name="data" type="binary" >
<column name="data" />
</property>
适用于.PDF,.TXT,.PNG等所有类型的文件,
答案 6 :(得分:-4)
在客户端设置“Content-Type:multipart / form-data”,这应该可以完成工作