尝试将文件上传到JAX-RS(泽西岛)服务器
我正在尝试使用带有Jersey的multipart / form-data客户端上传文件和其他表单数据。 我也使用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--
我在客户端做错了什么才能使其正常工作?
如果要将字符串添加到FormDataMultiPart
只需使用.field("name", "value")
方法,就像它用于文件附件一样(queryParam不起作用)。
以下是工作样本:
首先,服务器部分将读取的文件的内容作为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(); } }
二,发布文件的客户端方法:
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依赖:
junit junit 4.8.2 test com.sun.jersey jersey-server 1.6 com.sun.jersey jersey-client 1.6 com.sun.jersey.contribs jersey-multipart 1.6 org.mortbay.jetty jetty-embedded 6.1.26 commons-io commons-io 2.0.1
file.txt
位于类路径的根目录,包含Hello, World
。
Yves解决方案在客户端不适合我。 我环顾四周,发现:
- http://puspendu.wordpress.com/2012/08/23/restful-webservice-file-upload-with-jersey/
- http://neopatel.blogspot.de/2011/04/jersey-posting-multipart-data.html
- http://www.mkyong.com/webservices/jax-rs/file-upload-example-in-jersey/
不适用于我目前的jersey1.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提取:
1.18
com.sun.jersey jersey-server ${jersey.version} com.sun.jersey jersey-client ${jersey.version} com.sun.jersey.contribs jersey-multipart ${jersey.version}
public DssResponse callPut(String url, Map 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 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; }
或者只是写一个新文件并上传它:
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);