在 JAVA 中使用 Rest API 客户端上传文件

Posted

技术标签:

【中文标题】在 JAVA 中使用 Rest API 客户端上传文件【英文标题】:File Upload Using Rest API Client in JAVA 【发布时间】:2021-10-14 04:48:48 【问题描述】:

我创建了一个客户端 rest api 来在 api 端点上上传文件。但这给了我错误:

Exception in thread "main" org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=multipart/form-data, type=class org.glassfish.jersey.media.multipart.FormDataMultiPart, genericType=class org.glassfish.jersey.media.multipart.FormDataMultiPart.
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterceptorExecutor.java:191)
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:139)
    at org.glassfish.jersey.message.internal.MessageBodyFactory.writeTo(MessageBodyFactory.java:1005)
    at org.glassfish.jersey.client.ClientRequest.writeEntity(ClientRequest.java:430)
    at org.glassfish.jersey.client.HttpUrlConnector._apply(HttpUrlConnector.java:287)
    at org.glassfish.jersey.client.HttpUrlConnector.apply(HttpUrlConnector.java:200)
    at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:215)
    at org.glassfish.jersey.client.JerseyInvocation$1.call(JerseyInvocation.java:635)
    at org.glassfish.jersey.client.JerseyInvocation$1.call(JerseyInvocation.java:632)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:228)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:421)
    at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:632)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:392)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.post(JerseyInvocation.java:301)
    at Test.main(Test.java:35)

这是我的客户端休息 api 代码:

import java.io.File;

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Response;

import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
import org.glassfish.jersey.media.multipart.MultiPart;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.media.multipart.file.FileDataBodyPart;

public class Test 

    public void configureClient(ClientConfig config) 
        config.register(MultiPartFeature.class);
    
    public static void main(String[] args) 
        
        Client client = ClientBuilder.newClient().register(MultiPart.class);
        WebTarget server = client.target("http://localhost:8080/repositories/file/upload");
        
        FileDataBodyPart filePart = new FileDataBodyPart("file", new File("C:\\Users\\kunal\\Downloads\\JWTUtility.java"));
        filePart.setContentDisposition(FormDataContentDisposition.name("file").fileName("JWTUtility.java").build());
        
        MultiPart multipartEntity = new FormDataMultiPart().bodyPart(filePart);
        
        Response result = server.request().post(Entity.entity(multipartEntity, multipartEntity.getMediaType()));
        
        System.out.println(result.getStatus());
        System.out.println(result.readEntity(String.class));

        result.close();
        //assertEquals(Response.Status.OK.getStatusCode(), result.getStatus());
    


API 端点代码:

package com.howtodoinjava.jersey;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;

@Path("/upload")
public class JerseyService 

    @POST
    @Path("/pdf")
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public Response uploadPdfFile(  @FormDataParam("file") InputStream fileInputStream,
                                    @FormDataParam("file") FormDataContentDisposition fileMetaData) throws Exception
    
        String UPLOAD_PATH = "D://Test/";
        try
        
            int read = 0;
            byte[] bytes = new byte[1024];
     
            OutputStream out = new FileOutputStream(new File(UPLOAD_PATH + fileMetaData.getFileName()));
            while ((read = fileInputStream.read(bytes)) != -1)
            
                out.write(bytes, 0, read);
            
            out.flush();
            out.close();
         catch (IOException e)
        
            throw new WebApplicationException("Error while uploading file. Please try again !!");
        
        return Response.ok("Data uploaded successfully !!").build();
    

【问题讨论】:

.register(MultiPart.class) -> 需要注册MultiPartFeature 【参考方案1】:

在客户端,您需要添加对multipart/form-data 功能的支持,该功能将注册所需的读取器和写入器:

public class Test 

    public void configureClient(ClientConfig config) 
        config.register(MultiPartFeature.class);
    

    public static void main(String[] args) 
        DefaultClientConfig config = new DefaultClientConfig();
        configureClient(config);
        Client client = ClientBuilder.newClient(config);
        WebTarget server = client.target("http://localhost:8080/repositories/file/upload");
        // or alternatively at the WebTarget level
        // server.register(MultiPartFeature.class);
        
        // ...
    


【讨论】:

以上是关于在 JAVA 中使用 Rest API 客户端上传文件的主要内容,如果未能解决你的问题,请参考以下文章

以 InputStream 格式将文本文件从 .Net http 客户端上传到 Java REST API

使用 Spring REST API 上传文件

使用 REST API 的 Dropbox 差异/增量上传

我如何将在本地工作的 Web 服务(REST api,在 java 中)上传到主机服务器

如何在 Delphi 中使用 DropBox REST API 复制文件

使用 Angular2 将文件上传到 REST API