2014-12-22 17 views
35

我想通过上载图像和员工数据在系统中创建员工信息。我可以用不同的休息电话来使用球衣。但我想在一个休息电话中实现。我在下面提供了结构。请帮我在这方面做些什么。在泽西平静的web服务中与其他对象一起上传文件

@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": "[email protected]", 
    "Adrs": { 
     "DoorNo": "12-A", 
     "Street": "Street-11", 
     "City": "Bangalore", 
     "Country": "Karnataka" 
    } 
} 

但是我可以通过使两个不同的调用做到这一点,但我想在一个REST调用来实现,这样我可以接收文件,以及员工的实际数据。

请求您在这方面提供帮助。

回答

63

你不能有两个Content-Type(技术上这是我们下面做的,但它们与多部分的每个部分分开,但主要类型是多部分)。这基本上是你用你的方法期待的。您正在期待将mutlipart json作为主要媒体类型。 Employee数据需要成为multipart的一部分。因此,您可以为Employee添加@FormDataParam("emp")

@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 
      = "{\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(); 
} 

我刚刚创建了一个简单Employee类与类idname字段进行测试。这工作非常好。它显示图像,打印内容配置,并打印Employee对象。

我不是太熟悉的邮差,所以我保存的测试去年:-)

enter image description here

这似乎做工精细而且,正如你所看到的响应"Cool Tools"。但是,如果我们查看打印的Employee数据,我们会看到它是空的。这很奇怪,因为客户端API工作正常。

如果我们在预览窗口中,我们将看到的问题

enter image description here

有没有Content-Type标题为emp身体部位。您可以将客户端API中看到我明确设置

MultiPart multipartEntity = new FormDataMultiPart() 
     .field("emp", empPartJson, MediaType.APPLICATION_JSON_TYPE) 
     .bodyPart(filePart); 

所以我想这是真的只有一个完整的答案的一部分。就像我说的,我对邮差不熟悉所以我不知道如何为个人身体部位设置Content-Type。该图像的image/png是我为图像部分明确设置的。如果你能弄清楚这个问题,那么问题应该解决。请,如果你发现如何做到这一点,请将其作为答案。


而只是为了完整性......

基本配置:

相关性:

<dependency> 
    <groupId>org.glassfish.jersey.media</groupId> 
    <artifactId>jersey-media-multipart</artifactId> 
    <version>2.14</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); 

UPDATE

所以你可以从邮差客户端看到,某些客户端将无法设置单个零件的内容类型,这包括浏览器,在关于它使用时的默认功能FormData(JS)。

我们不能指望客户找到这个东西,所以我们可以做的是在接收数据时,在反序列化之前明确设置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,但它比强制客户端,试图找到它自己的解决方案更好的解决方案。

+0

嗨,我可以请你麻烦你(或任何其他善良的灵魂谁读这个,知道)更新客户端API中的代码。例如,第一行有“c.target”,但这里的c是什么? – AbuMariam

+0

@ user3223841请参阅最底部的“客户端配置”。 'c == client'。我更新了代码。谢谢。 –

+0

你在大文件上测试过你的代码吗?我在表单提交时得到[相同](http://stackoverflow.com/q/10326460/660408)错误 – gkiko

1

您可以通过使用下面的代码从窗体访问图像文件和数据。

@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) {} 
     } 
    } 
} 
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); 
    } 
0

我使用的文件上传例子来自

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); 

     } 
在道

我在HBM映射有

attach.setData(is); 
attach.setFileName(flename); 

就像

<property name="data" type="binary" > 
      <column name="data" /> 
</property> 

这工作对所有类型的文件,如.PDF,.TXT,.PNG等,

+0

你只是用byte []参数而不是InputStream保存我的生活... @Ramam我欠你一杯啤酒! –

0

我想加上peeskillet注释,但没有50点声望,因此将作为一个答案:

当我试图@peeskillet解决方案与Jersey客户端2.21.1,有400错误。

MediaType contentType = MediaType.MULTIPART_FORM_DATA_TYPE; 
    contentType = Boundary.addBoundary(contentType); 

    Response response = t.request().post(
     Entity.entity(multipartEntity, contentType)); 

而不是POST请求调用硬编码MediaType.MULTIPART_FORM_DATA:当我在我的客户端代码添加以下工作。