在Jersey平安Web服务中与其他对象一起上传文件
我想通过上传图片和员工数据来在系统中创build员工信息。 我可以用不同的rest电话使用泽西岛。 但是我想在一个rest电话中实现。 我在结构下面提供。 请帮我在这方面怎么做。
@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" } }
不过,我可以做两个不同的调用,但我想在一个rest电话,以便我可以接收文件以及员工的实际数据。
请求你在这方面的帮助。
你不能有两个Content-Type
(技术上这是我们在下面做的,但是它们与多部分的每个部分分开,但是主types是多部分的)。 这基本上是你所期望的方法。 你期待mutlipart 和 JSON作为主要的媒体types。 Employee
数据需要成为多部分的一部分。 所以你可以为Employee
添加一个@FormDataParam("emp")
。
@FormDataParam("emp") Employee emp) { ...
这是我用来testing的课程
@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(); } }
首先,我只是testing客户端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 = "{\n" + " \"id\": 1234,\n" + " \"name\": \"Peeskillet\"\n" + "}\n" + ""; 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(); }
我刚创build了一个带有id
和name
字段的简单Employee
类进行testing。 这工作得很好。 它显示图像,打印内容configuration,并打印Employee
对象。
我不太熟悉邮差,所以我保存了最后的testing:-)
它似乎也正常工作,因为你可以看到响应"Cool Tools"
。 但是,如果我们查看打印的Employee
数据,我们会看到它是空的。 这是奇怪的,因为客户端API工作正常。
如果我们看预览窗口,我们会看到问题
没有Content-Type
头文件的身体部分。 你可以在客户端API中看到我明确地设置它
MultiPart multipartEntity = new FormDataMultiPart() .field("emp", empPartJson, MediaType.APPLICATION_JSON_TYPE) .bodyPart(filePart);
所以我想这只是一个完整答案的一部分 。 就像我说的,我不熟悉邮差所以我不知道如何设置个人身体部位的Content-Type
。 image/png
是为图像部分明确设置的。 如果你能弄清楚这个问题,那么问题就应该解决了。 请,如果你发现如何做到这一点,张贴作为答案。
为了完整性
- 请参阅这里了解有关Jersey的多部件的更多信息 。
基本configuration:
相关性:
<dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-multipart</artifactId> <version>2.14</version> </dependency>
客户端configuration:
final Client client = ClientBuilder.newBuilder() .register(MultiPartFeature.class) .build();
服务器configuration:
// Create JAX-RS application. final Application application = new ResourceConfig() .packages("org.glassfish.jersey.examples.multipart") .register(MultiPartFeature.class);
UPDATE
正如你从Postman客户端可以看到的那样,一些客户端在使用FormData
(js)时,无法设置各个部分的Content-Type,这包括浏览器,就其默认function而言。
我们不能期望客户端发现这个,所以我们可以做的是在接收数据时,在反序列化之前明确地设置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是一件额外的工作,但这比强迫客户尝试find自己的解决scheme更好。
您可以使用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) {} } } }
您的ApplicationConfig应该注册glassfish.jersey.media ..中的MultiPartFeature.class,以启用file upload
@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); }
我用file upload的例子来说,
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等所有types的文件,
我想添加对peeskillet的评论,但是没有50点声望点,因此增加了一个答案:
当我用Jersey客户端2.21.1试过@peeskillet解决scheme时,出现了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。