尝试将文件上传到 JAX-RS (jersey) 服务器

发布于 2024-11-03 06:45:18 字数 2893 浏览 1 评论 0原文

我正在尝试使用带有 Jersey 的多部分/表单数据客户端上传文件和其他表单数据。我也使用 Jersey 上传到 REST Web 服务。这是服务器代码:

@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_JSON)
public String create(@FormDataParam("file") InputStream file,
        @FormDataParam("file") FormDataContentDisposition fileInfo,
        @FormDataParam("name") String name,
        @FormDataParam("description") String description) {
    Ingredient ingredient = new Ingredient();
    ingredient.setName(name);
    ingredient.setDescription(description);
    ingredient.setImageName(fileInfo.getFileName());
    ingredient.setImagePath(context.getRealPath("/resources/uploads/"));
    // TODO save the file.
    try {
        JSONObject json = new JSONObject();
        try {
            ingredientService.create(ingredient);
        } catch (final InvalidParameterException ex) {
            logger.log(Level.INFO, ex.getMessage());
            json.put("result", false);
            json.put("error", ex.getMessage());
            return json.toString();
        } catch (final GoodDrinksException ex) {
            logger.log(Level.WARNING, null, ex);
            json.put("result", false);
            json.put("error", ex.getMessage());
            return json.toString();
        }
        json.put("ingredient", JsonUtil.ingredientToJSON(ingredient));
        return json.put("result", true).toString();
    } catch (JSONException ex) {
        logger.log(Level.SEVERE, null, ex);
        return "{\"result\",false}";
    }
}

我已经在桌面上使用基本 html 表单测试了服务器代码,它工作正常。问题似乎出在客户端。这是相关的客户端代码。

ClientConfig config = new DefaultClientConfig();
client = Client.create(config);
client.addFilter(new LoggingFilter());
webResource = client.resource("http://localhost:8080/webapp/resources").path("ingredient");
FormDataMultiPart fdmp = new FormDataMultiPart();
if (file != null) {
    fdmp.bodyPart(new FileDataBodyPart("file", file, MediaType.APPLICATION_OCTET_STREAM_TYPE));
}
fdmp.bodyPart(new FormDataBodyPart("name", ingredient.getName()));
fdmp.bodyPart(new FormDataBodyPart("description", ingredient.getDescription()));

ClientResponse response = webResource.type(MediaType.MULTIPART_FORM_DATA_TYPE).post(ClientResponse.class, fdmp);
String string = response.getEntity(String.class);
logger.log(Level.INFO, "response: {0}", string);

我从服务器收到 400 响应“客户端发送的请求在语法上不正确”

这是从记录器中吐出的消息,这个消息没有文件来保持输出简短:

1 > POST http://localhost:8080/webapp/resources/ingredient  
1 > Content-Type: multipart/form-data  
1 >   
--Boundary_5_1545082086_1303666703655  
Content-Type: text/plain  
Content-Disposition: form-data;name="name"  
Adam  
--Boundary_5_1545082086_1303666703655  
Content-Type: text/plain  
Content-Disposition: form-data;name="description"  
Test  
--Boundary_5_1545082086_1303666703655--  

我做错了什么在客户端中使其正常工作?

I'm trying to upload a file and other form data using multipart/form-data client with Jersey. I'm uploading to a REST web service also using Jersey. Here is the server code:

@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_JSON)
public String create(@FormDataParam("file") InputStream file,
        @FormDataParam("file") FormDataContentDisposition fileInfo,
        @FormDataParam("name") String name,
        @FormDataParam("description") String description) {
    Ingredient ingredient = new Ingredient();
    ingredient.setName(name);
    ingredient.setDescription(description);
    ingredient.setImageName(fileInfo.getFileName());
    ingredient.setImagePath(context.getRealPath("/resources/uploads/"));
    // TODO save the file.
    try {
        JSONObject json = new JSONObject();
        try {
            ingredientService.create(ingredient);
        } catch (final InvalidParameterException ex) {
            logger.log(Level.INFO, ex.getMessage());
            json.put("result", false);
            json.put("error", ex.getMessage());
            return json.toString();
        } catch (final GoodDrinksException ex) {
            logger.log(Level.WARNING, null, ex);
            json.put("result", false);
            json.put("error", ex.getMessage());
            return json.toString();
        }
        json.put("ingredient", JsonUtil.ingredientToJSON(ingredient));
        return json.put("result", true).toString();
    } catch (JSONException ex) {
        logger.log(Level.SEVERE, null, ex);
        return "{\"result\",false}";
    }
}

I've tested the server code using a basic html form on my desktop and it works fine. The problem seems to be in the client. Here is the relevant client code.

ClientConfig config = new DefaultClientConfig();
client = Client.create(config);
client.addFilter(new LoggingFilter());
webResource = client.resource("http://localhost:8080/webapp/resources").path("ingredient");
FormDataMultiPart fdmp = new FormDataMultiPart();
if (file != null) {
    fdmp.bodyPart(new FileDataBodyPart("file", file, MediaType.APPLICATION_OCTET_STREAM_TYPE));
}
fdmp.bodyPart(new FormDataBodyPart("name", ingredient.getName()));
fdmp.bodyPart(new FormDataBodyPart("description", ingredient.getDescription()));

ClientResponse response = webResource.type(MediaType.MULTIPART_FORM_DATA_TYPE).post(ClientResponse.class, fdmp);
String string = response.getEntity(String.class);
logger.log(Level.INFO, "response: {0}", string);

I'm getting a 400 response from the server "The request sent by the client was syntactically incorrect"

Here is the message that is spit out of the logger, this one is without a file to keep the output brief:

1 > POST http://localhost:8080/webapp/resources/ingredient  
1 > Content-Type: multipart/form-data  
1 >   
--Boundary_5_1545082086_1303666703655  
Content-Type: text/plain  
Content-Disposition: form-data;name="name"  
Adam  
--Boundary_5_1545082086_1303666703655  
Content-Type: text/plain  
Content-Disposition: form-data;name="description"  
Test  
--Boundary_5_1545082086_1303666703655--  

What am I doing wrong in the client to get this working correctly?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

朱染 2024-11-10 06:45:18

如果要将字符串添加到 FormDataMultiPart,只需使用 .field("name", "value") 方法,就像用于文件附件 (queryParam不起作用)。

下面是一个工作示例:

首先,服务器部分以字符串形式返回读取文件的内容:

@Path("file")
public class FileResource {

    @POST
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public Response handleUpload(@FormDataParam("file") InputStream stream) throws Exception {
        return Response.ok(IOUtils.toString(stream)).build();
    }
}

其次,发布文件的客户端方法:

public void upload(String url, String fileName) {
    InputStream stream = getClass().getClassLoader().getResourceAsStream(fileName);
    FormDataMultiPart part = new FormDataMultiPart().field("file", stream, MediaType.TEXT_PLAIN_TYPE);

    WebResource resource = Client.create().resource(url);
    String response = resource.type(MediaType.MULTIPART_FORM_DATA_TYPE).post(String.class, part);
    assertEquals("Hello, World", response);
}

第三,测试环境:

Server server;

@Before
public void before() throws Exception {
    server = new Server(8080);
    server.addHandler(new WebAppContext(WEB_INF_DIRECTORY, "/"));
    server.start(); 
}

@After
public void after() throws Exception {
    server.stop();
}

@Test
public void upload() {
    upload("http://localhost:8080/file", "file.txt");
}

最后,maven 依赖项:

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.8.2</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>com.sun.jersey</groupId>
        <artifactId>jersey-server</artifactId>
        <version>1.6</version>
    </dependency>
    <dependency>
        <groupId>com.sun.jersey</groupId>
        <artifactId>jersey-client</artifactId>
        <version>1.6</version>
    </dependency>
    <dependency>
        <groupId>com.sun.jersey.contribs</groupId>
        <artifactId>jersey-multipart</artifactId>
        <version>1.6</version>
    </dependency>
    <dependency>
        <groupId>org.mortbay.jetty</groupId>
        <artifactId>jetty-embedded</artifactId>
        <version>6.1.26</version>
    </dependency>
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.0.1</version>
    </dependency>
</dependencies>

文件。 txt 位于类路径的根目录,包含 Hello, World

If you want to add Strings to the FormDataMultiPart just use the .field("name", "value") method the same way it is used for the file attachment (queryParam does not work).

Below is a working sample:

First, the server part which returns the content of the read file as a String:

@Path("file")
public class FileResource {

    @POST
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public Response handleUpload(@FormDataParam("file") InputStream stream) throws Exception {
        return Response.ok(IOUtils.toString(stream)).build();
    }
}

Second, the client method posting the file:

public void upload(String url, String fileName) {
    InputStream stream = getClass().getClassLoader().getResourceAsStream(fileName);
    FormDataMultiPart part = new FormDataMultiPart().field("file", stream, MediaType.TEXT_PLAIN_TYPE);

    WebResource resource = Client.create().resource(url);
    String response = resource.type(MediaType.MULTIPART_FORM_DATA_TYPE).post(String.class, part);
    assertEquals("Hello, World", response);
}

Third, the test environment:

Server server;

@Before
public void before() throws Exception {
    server = new Server(8080);
    server.addHandler(new WebAppContext(WEB_INF_DIRECTORY, "/"));
    server.start(); 
}

@After
public void after() throws Exception {
    server.stop();
}

@Test
public void upload() {
    upload("http://localhost:8080/file", "file.txt");
}

Finally, the maven dependencies:

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.8.2</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>com.sun.jersey</groupId>
        <artifactId>jersey-server</artifactId>
        <version>1.6</version>
    </dependency>
    <dependency>
        <groupId>com.sun.jersey</groupId>
        <artifactId>jersey-client</artifactId>
        <version>1.6</version>
    </dependency>
    <dependency>
        <groupId>com.sun.jersey.contribs</groupId>
        <artifactId>jersey-multipart</artifactId>
        <version>1.6</version>
    </dependency>
    <dependency>
        <groupId>org.mortbay.jetty</groupId>
        <artifactId>jetty-embedded</artifactId>
        <version>6.1.26</version>
    </dependency>
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.0.1</version>
    </dependency>
</dependencies>

The file.txt is at the root of the classpath and contains Hello, World.

行至春深 2024-11-10 06:45:18

伊夫解决方案在客户端对我不起作用。
我环顾四周,发现:

其中任何一个都不适用于我当前的球衣 1.18(请参阅下面的 pom 摘录)。
大多数问题都在客户端。我会收到如下错误消息:

com.sun.jersey.api.client.ClientHandlerException: javax.ws.rs.WebApplicationException: java.lang.IllegalArgumentException: Missing body part entity of type 'text/plain'
at com.sun.jersey.client.urlconnection.URLConnectionClientHandler.handle(URLConnectionClientHandler.java:155)
at com.sun.jersey.api.client.Client.handle(Client.java:652)
at com.sun.jersey.api.client.WebResource.handle(WebResource.java:682)

服务器端使用此代码快速工作(它没有做任何有趣的事情)
上传的InputStream - 满足您的需求)

@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces("text/plain")
public Response uploadFile(
        @FormDataParam("content") final InputStream uploadedInputStream,
        @FormDataParam("fileName") String fileName) throws IOException {
    String uploadContent=IOUtils.toString(uploadedInputStream);
    return Response.ok(uploadContent).build();
}   

客户端将使用以下代码:

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;   
import javax.ws.rs.core.MediaType;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.multipart.FormDataBodyPart;
import com.sun.jersey.multipart.FormDataMultiPart;
/**
 * upload the given file
 * 
 * inspired by
 * http://neopatel.blogspot.de/2011/04/jersey-posting-multipart-data.html
 * 
 * @param url
 * @param uploadFile
 * @return the result
 * @throws IOException
 */
public String upload(String url, File uploadFile) throws IOException {
    WebResource resource = Client.create().resource(url);
    FormDataMultiPart form = new FormDataMultiPart();
    form.field("fileName", uploadFile.getName());
    FormDataBodyPart fdp = new FormDataBodyPart("content",
            new FileInputStream(uploadFile),
            MediaType.APPLICATION_OCTET_STREAM_TYPE);
    form.bodyPart(fdp);
    String response = resource.type(MediaType.MULTIPART_FORM_DATA).post(String.class, form);
    return response;
}

pom.xml 提取:

<properties>
  <jersey.version>1.18</jersey.version>
</properties>
<dependency>
  <groupId>com.sun.jersey</groupId>
  <artifactId>jersey-server</artifactId>
  <version>${jersey.version}</version>
</dependency>
<dependency>
  <groupId>com.sun.jersey</groupId>
  <artifactId>jersey-client</artifactId>
  <version>${jersey.version}</version>
</dependency>
<!--  Multipart support -->
<dependency>
  <groupId>com.sun.jersey.contribs</groupId>
  <artifactId>jersey-multipart</artifactId>
  <version>${jersey.version}</version>
</dependency>

Yves solution didn't work for me on the client side.
I looked around a bit and found:

non of which would work with my current jersey 1.18 (see pom extract below).
Most trouble was on the client side. I would get error messages like:

com.sun.jersey.api.client.ClientHandlerException: javax.ws.rs.WebApplicationException: java.lang.IllegalArgumentException: Missing body part entity of type 'text/plain'
at com.sun.jersey.client.urlconnection.URLConnectionClientHandler.handle(URLConnectionClientHandler.java:155)
at com.sun.jersey.api.client.Client.handle(Client.java:652)
at com.sun.jersey.api.client.WebResource.handle(WebResource.java:682)

The server side worked quickly with this code (which doesn't do anything interesting with
the uploaded InputStream yet - fit to your needs )

@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces("text/plain")
public Response uploadFile(
        @FormDataParam("content") final InputStream uploadedInputStream,
        @FormDataParam("fileName") String fileName) throws IOException {
    String uploadContent=IOUtils.toString(uploadedInputStream);
    return Response.ok(uploadContent).build();
}   

the client side would work with this code:

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;   
import javax.ws.rs.core.MediaType;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.multipart.FormDataBodyPart;
import com.sun.jersey.multipart.FormDataMultiPart;
/**
 * upload the given file
 * 
 * inspired by
 * http://neopatel.blogspot.de/2011/04/jersey-posting-multipart-data.html
 * 
 * @param url
 * @param uploadFile
 * @return the result
 * @throws IOException
 */
public String upload(String url, File uploadFile) throws IOException {
    WebResource resource = Client.create().resource(url);
    FormDataMultiPart form = new FormDataMultiPart();
    form.field("fileName", uploadFile.getName());
    FormDataBodyPart fdp = new FormDataBodyPart("content",
            new FileInputStream(uploadFile),
            MediaType.APPLICATION_OCTET_STREAM_TYPE);
    form.bodyPart(fdp);
    String response = resource.type(MediaType.MULTIPART_FORM_DATA).post(String.class, form);
    return response;
}

pom.xml extract:

<properties>
  <jersey.version>1.18</jersey.version>
</properties>
<dependency>
  <groupId>com.sun.jersey</groupId>
  <artifactId>jersey-server</artifactId>
  <version>${jersey.version}</version>
</dependency>
<dependency>
  <groupId>com.sun.jersey</groupId>
  <artifactId>jersey-client</artifactId>
  <version>${jersey.version}</version>
</dependency>
<!--  Multipart support -->
<dependency>
  <groupId>com.sun.jersey.contribs</groupId>
  <artifactId>jersey-multipart</artifactId>
  <version>${jersey.version}</version>
</dependency>
海未深 2024-11-10 06:45:18
public DssResponse callPut(String url, Map<String, String> headers, FileDataBodyPart[] filePath, String boundary, String[] jsonString) throws IOException {
    Client client = ClientBuilder.newClient().register(MultiPartFeature.class);
    WebTarget webTarget = client.target(url);
    Builder builder = webTarget.request(MediaType.MULTIPART_FORM_DATA);
    FormDataMultiPart multiPart = new FormDataMultiPart();
    for (int i = 0; i < filePath.length; i++) {

        if (!filePath[i].getFileEntity().exists()) {
            throw new IOException("Invalid Input File - " + filePath[i].getFileEntity().getAbsolutePath());
        }

        multiPart.bodyPart(new FileDataBodyPart(filePath[i].getName(), filePath[i].getFileEntity()));
    }

    if (boundary != null)
        multiPart.type(Boundary.addBoundary(new MediaType("multipart", "form-data", Collections.singletonMap(Boundary.BOUNDARY_PARAMETER, boundary))));
    for (String jstr : jsonString) {
        multiPart.field("Content-Type", jstr, MediaType.APPLICATION_JSON_TYPE);
    }
    if (headers != null) {
        for (Entry<String, String> header : headers.entrySet()) {
            builder.header(header.getKey(), header.getValue());
            System.out.println(header.getKey() + "===============>>" + header.getValue());
        }
    }

    Response response = builder.accept(MediaType.APPLICATION_JSON).put(Entity.entity(multiPart, multiPart.getMediaType()));

    multiPart.close();

    // Assert.assertNotNull(response);
    if (response == null )
        throw new IOException ("Response is NULL");

    int status = response.getStatus();

    return dssResponse;
}
public DssResponse callPut(String url, Map<String, String> headers, FileDataBodyPart[] filePath, String boundary, String[] jsonString) throws IOException {
    Client client = ClientBuilder.newClient().register(MultiPartFeature.class);
    WebTarget webTarget = client.target(url);
    Builder builder = webTarget.request(MediaType.MULTIPART_FORM_DATA);
    FormDataMultiPart multiPart = new FormDataMultiPart();
    for (int i = 0; i < filePath.length; i++) {

        if (!filePath[i].getFileEntity().exists()) {
            throw new IOException("Invalid Input File - " + filePath[i].getFileEntity().getAbsolutePath());
        }

        multiPart.bodyPart(new FileDataBodyPart(filePath[i].getName(), filePath[i].getFileEntity()));
    }

    if (boundary != null)
        multiPart.type(Boundary.addBoundary(new MediaType("multipart", "form-data", Collections.singletonMap(Boundary.BOUNDARY_PARAMETER, boundary))));
    for (String jstr : jsonString) {
        multiPart.field("Content-Type", jstr, MediaType.APPLICATION_JSON_TYPE);
    }
    if (headers != null) {
        for (Entry<String, String> header : headers.entrySet()) {
            builder.header(header.getKey(), header.getValue());
            System.out.println(header.getKey() + "===============>>" + header.getValue());
        }
    }

    Response response = builder.accept(MediaType.APPLICATION_JSON).put(Entity.entity(multiPart, multiPart.getMediaType()));

    multiPart.close();

    // Assert.assertNotNull(response);
    if (response == null )
        throw new IOException ("Response is NULL");

    int status = response.getStatus();

    return dssResponse;
}
天涯离梦残月幽梦 2024-11-10 06:45:18

或者只是编写一个新文件并上传:

Writer output = null;
    File file = null;
    try {
      String text = "Rajesh Kumar";
      file = new File("write.txt");
      output = new BufferedWriter(new FileWriter(file));
        output.write(text);
        output.close();
    } catch (IOException e) {
        System.out.println("IOException e");
        e.printStackTrace();
    }

    InputStream is = null;

    try {
        is = new FileInputStream(file);
    } catch (FileNotFoundException e) {
        System.out.println("FileNotFoundException e");
        e.printStackTrace();
    } catch (IOException e) {
        System.out.println("IOException e");
        e.printStackTrace();
    }

    FormDataMultiPart part = new FormDataMultiPart().field("file", is, MediaType.TEXT_PLAIN_TYPE);
    res = service.path("rest").path("tenant").path(tenant1.getTenantId()).path("file").type(MediaType.MULTIPART_FORM_DATA_TYPE).post(ClientResponse.class, part);

Or just write a new file and upload it:

Writer output = null;
    File file = null;
    try {
      String text = "Rajesh Kumar";
      file = new File("write.txt");
      output = new BufferedWriter(new FileWriter(file));
        output.write(text);
        output.close();
    } catch (IOException e) {
        System.out.println("IOException e");
        e.printStackTrace();
    }

    InputStream is = null;

    try {
        is = new FileInputStream(file);
    } catch (FileNotFoundException e) {
        System.out.println("FileNotFoundException e");
        e.printStackTrace();
    } catch (IOException e) {
        System.out.println("IOException e");
        e.printStackTrace();
    }

    FormDataMultiPart part = new FormDataMultiPart().field("file", is, MediaType.TEXT_PLAIN_TYPE);
    res = service.path("rest").path("tenant").path(tenant1.getTenantId()).path("file").type(MediaType.MULTIPART_FORM_DATA_TYPE).post(ClientResponse.class, part);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文