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

Posted

技术标签:

【中文标题】以 InputStream 格式将文本文件从 .Net http 客户端上传到 Java REST API【英文标题】:Upload a text File from .Net http client to Java REST API in InputStream format 【发布时间】:2016-12-23 15:15:02 【问题描述】:

我有一个案例,我想。当我从 Postman 使用 Form-Data Body 中的文件点击 Java REST 时,该文件在 Java REST 服务中被很好地接收。当我尝试来自 .Net 客户端的相同操作时,我遇到了一些异常,如下所示。

我的 .Net HTTP 客户端代码如下,

var client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:8082/processes/view/createDocumentfromFile/851");
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("procId", "100");
client.DefaultRequestHeaders.Add("DocName", "ProphetWorkflow");
var content = new MultipartFormDataContent();
content.Add(new ByteArrayContent(File.ReadAllBytes(@"C:\Users\charan.ghate\Desktop\Calculation.txt")));
HttpResponseMessage messge = client.PostAsync(client.BaseAddress, content).Result;
if (messge.IsSuccessStatusCode)

    string result = messge.Content.ReadAsStringAsync().Result;
    lblResponse.Text = result;

我的 Java REST 服务代码如下,

@POST
@Path("/createDocumentfromFile/procId")
@Consumes( MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN )
@Produces( MediaType.APPLICATION_JSON )
public Response createDocumentfromFile(@PathParam("procId") Long piOID, @HeaderParam("DocName") String modulename,
        @Context HttpServletRequest request, @Context HttpServletResponse response,
        @FormDataParam("file") InputStream uploadedInputStream) 
//
//Operation on the input stream
//

当我点击 REST API 时,我在 .Net 和 Java 中都遇到了异常,详情如下

.Net 错误消息:

StatusCode: 500, ReasonPhrase: 'Internal Server Error', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:

  Connection: close
  Date: Fri, 23 Dec 2016 15:08:03 GMT
  Server: Apache-Coyote/1.

Java 异常:

    Dec 23, 2016 8:38:03 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [cxf-jaxrs-servlet] in context with path [/ipp-portal] threw exception [Servlet execution threw an exception] with root cause
java.lang.NoSuchMethodError: javax.ws.rs.ClientErrorException.validate(Ljavax/ws/rs/core/Response;Ljavax/ws/rs/core/Response$Status$Family;)Ljavax/ws/rs/core/Response;
    at javax.ws.rs.ClientErrorException.<init>(ClientErrorException.java:88)
    at org.apache.cxf.jaxrs.utils.JAXRSUtils.findTargetMethod(JAXRSUtils.java:503)
    at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.processRequest(JAXRSInInterceptor.java:198)
    at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.handleMessage(JAXRSInInterceptor.java:90)
    at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272)
    at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
    at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:239)
    at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:248)
    at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:222)
    at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:153)
    at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:167)
    at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:286)
    at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:206)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:650)
    at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:262)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.eclipse.stardust.ui.web.html5.EnhancedJarResourceFilter.doFilter(EnhancedJarResourceFilter.java:140)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at com.icesoft.faces.webapp.http.servlet.TouchSessionFilter.doFilter(TouchSessionFilter.java:77)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:956)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:436)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1078)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:625)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)

您能否建议我将文件从 .Net 客户端传输到 Java REST 服务的最佳方法。

【问题讨论】:

【参考方案1】:

异常

java.lang.NoSuchMethodError: javax.ws.rs.ClientErrorException.validate(Ljavax/ws/rs/core/Response;Ljavax/ws/rs/core/Response$Status$Family;)Ljavax/ws/rs/core/Response;

意味着它试图在运行时从它找不到的类ClientErrorException 中获取类型为Response validate(final Response response, Response.Status.Family expectedStatusFamily) 的方法。

当您使用库的一个版本构建应用程序并针对不兼容的不同版本运行它时,通常会发生这种情况。

知道自JAX-RS 2.0 以来已添加此方法,我相信您使用JAX-RS 2.0 或更高版本编译了您的代码,并且您的类路径中有一个版本1.x 在运行时使用。检查运行时使用的类路径,并确保您只有在编译时使用的 JAX-RS 版本。

【讨论】:

【参考方案2】:

可能发生的情况是服务器不喜欢该请求,准备发送错误,并且由于库不匹配而失败(正如 Nicolas Filotto 所指出的那样)。这就是为什么您会看到一般的 HTTP 500 错误,而不是一些(更多信息)4XX。

解决库版本不匹配可能是一个好主意,即使它在请求与服务器期望的匹配时有效(如 Postman 所示)

看两边的签名,我能想到的是这样的:

MediaType.MULTIPART_FORM_DATA_TYPE 添加到消费的内容类型。

删除 client.DefaultRequestHeaders.Add("procId", "100");,因为 procId 应该在路径上,而不是在标题中。

添加file 作为ByteArrayContent 的名称:

content.Add(new ByteArrayContent(File.ReadAllBytes(@"C:\Users\charan.ghate\Desktop\Calculation.txt")), "file");

此外,您可以尝试禁用 .NET HttpClient 默认使用的 Expect: 100-continue 标头,某些服务器不处理它。

client.DefaultRequestHeaders.ExpectContinue = false;

【讨论】:

以上是关于以 InputStream 格式将文本文件从 .Net http 客户端上传到 Java REST API的主要内容,如果未能解决你的问题,请参考以下文章

如何将文本文件从 DOS 格式转换为 UNIX 格式

从多种格式的 InputStream 中读取

InputStream 连接到 URL 但不返回任何内容

java读取文件:二进制文件

从 Norand PL\N 格式转换为纯文本

如何从 Java 8 Streams 中获取 Inputstream?