前言

和上一篇文章一样,.NET 和 JAVA之间的接口请求又遇到了新问题

我们有一个用来接收文件的接口,外部把文件流、文件名、目录,传进来,我们系统把生成的附件ID反回去,接口为POST-form-data格式

我用POSTMAN调用没有问题,就把文档写好发出去了,结果.NET开发的兄弟就又进行不下去了

问题现象

一模一样的参数,POSTMAN里请求正常,C#请求就返回空,翻了一下我们的日志,

NullPointerException 这。。。也不知道是哪抛出来的,本来就是原有的接口,逻辑一大堆,只看日志也看不出个所以然。

而且客户的环境我还没办法远程debug,我本地环境又没办法让对方开发调。

于是乎我和他们远程会议一点点猜他代码的问题,该加的参数都加了,找不出来哪有毛病。

处理过程

最后本着能让他们改,我自己就不动的原则,我开始研究起来了C#,之前基本没怎么接触过,从准备环境开始。。。

详细的环境准备过程请看:

//TODO C#环境准备

因为本来就不怎么会写么,况且POSTMAN能调通,于是准备直接用POSTMAN生成的代码来测,就得到了这个:

    var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost:8080/api/doc/upload/uploadFile2Doc"); request.Headers.Add("appid", "CRM");
request.Headers.Add("token", "a3c6e10f-2269-4851-a3e4-3bb7bb1df183");
request.Headers.Add("userid", "EGqrxYColwBVopfkbVn/jUI7n9fPkRvcwnMh5LbNLuCkykywI902H3F98wvwlY8CWeHKXuiwLR8DmsCmupjcD1x79kMsNVkJOiq5N4y4Dj+CaFcelvdL+Nypgho3Sj4dPc/hRkbdXnvf4iAh8LR7v22pQOKuHm8I7ZclLID87JGKlsEs+X64CtJEJtTGh6js4PDBR5zWFB8NwxmcJHq4M26RNWeZVp7Tz93W5qv3WvgROUuuK7cla5gu8GgwqSJAQlti2VuNJpLIgTRNsB7UQeYCrGYNOTAU0JzDhAi+A3t7hA4eoWHb0+na/SLgR6sQrGzLk4KpO6rkU7PVCrHkjg=="); var content = new MultipartFormDataContent();
content.Add(new StreamContent(File.OpenRead("/C:/Users/13064/工作/测试文件/测试表格.xlsx")), "file", "/C:/Users/13064/工作/测试文件/测试表格.xlsx");
content.Add(new StringContent("测试表格.xlsx""), "name");
request.Content = content; var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());

不出所料,还是返回了个{}

不过好在是自己的环境,Debug,启动!

一层一层的找,发现这个NullPointerException 是因为拿到的file为null,于是我天真的揣测是不是header没有指定类型的问题

于是天真的加上了

    content.Headers.ContentType = new MediaTypeHeaderValue("multipart/form-data")

果不其然,报错变了

Separation boundary was not specified

这是个什么东西,之前没见过,简单搜了一下,表明 multipart/form-data 请求中缺少边界(boundary)信息

然后文档里还写 :MultipartFormDataContent确保你没有在请求中手动设置 Content-Type,因为 C# 会自动添加边界

好吧,画蛇添足了属于是

继续从JAVA侧入手吧,看看为什么file为null,继续深入,发现file不是没拿到,而是到file这个参数的时候出问题了,但是异常并没有抛出

直接在里面catch掉之后return了个null

java.lang.RuntimeException: >>>>Xss(NoPass),invalidChar in params:--->referer:null path:/api/doc/upload/uploadFile2Doc param:=?utf-8?B?5rWL6K+V6KGo5qC8Lnhsc3g=?= rule=(the value is too big!(1000000)) paramValue:PK

值超长?其实这会就该想到为什么了,但是没反应过来,新建了个TXT传,心想肯定不会超长了吧,结果倒是没超长,但是file还是没拿到

仔细看了下,发现file参数被当作了个普通param来处理的,怪不得文件大一点就超长了

既然这种请求方式JAVA侧拿不到正确的参数类型,那就换一种,于是就从POSTMAN又得到了这段代码

    var options = new RestClientOptions("http://localhost:8080")
{
MaxTimeout = -1,
}; var client = new RestClient(options);
var request = new RestRequest("/api/doc/upload/uploadFile2Doc", Method.Post);
request.AddHeader("appid", "CRM");
request.AddHeader("token", "a3c6e10f-2269-4851-a3e4-3bb7bb1df183");
request.AddHeader("userid", "EGqrxYColwBVopfkbVn/jUI7n9fPkRvcwnMh5LbNLuCkykywI902H3F98wvwlY8CWeHKXuiwLR8DmsCmupjcD1x79kMsNVkJOiq5N4y4Dj+CaFcelvdL+Nypgho3Sj4dPc/hRkbdXnvf4iAh8LR7v22pQOKuHm8I7ZclLID87JGKlsEs+X64CtJEJtTGh6js4PDBR5zWFB8NwxmcJHq4M26RNWeZVp7Tz93W5qv3WvgROUuuK7cla5gu8GgwqSJAQlti2VuNJpLIgTRNsB7UQeYCrGYNOTAU0JzDhAi+A3t7hA4eoWHb0+na/SLgR6sQrGzLk4KpO6rkU7PVCrHkjg==");
request.AddHeader("Cookie", "ecology_JSessionid=aaah7nfm2JXcVfjSBTajz; languageidweaver=7; loginidweaver=1");
request.AlwaysMultipartFormData = true;
request.AddFile("file", "/C:/Users/13064/工作/测试文件/测试表格.xlsx");
request.AddParameter("name", "测试表格.xlsx");
RestResponse response = await client.ExecuteAsync(request);
Console.WriteLine(response.Content);

调用一下,发现这次JAVA这边连debug都没进,而且C#这边也什么都没打出来

简单研究了一下RestResponse的用法

加上了如下代码

    if (response.IsSuccessful)
{
Console.WriteLine("请求成功:");
Console.WriteLine(response.Content);
}
else
{
Console.WriteLine("请求失败:");
Console.WriteLine($"状态码: {response.StatusCode}");
Console.WriteLine($"错误信息: {response.ErrorMessage}");
Console.WriteLine($"响应内容: {response.Content}");
}

状态码: NotAcceptable

继续添加

    request.AddHeader("Accept", "*/*");

再看JAVA侧,终于file是个文件了,回看C#也已经正确拿到了返回数据

完整代码

为了方便扔给那边的兄弟做测试,简单优化了下

    using RestSharp;
using Newtonsoft.Json.Linq; string uri = "http://127.0.0.1:8080"; var json = await GetToken();
var jsonObject = JObject.Parse(json);
string token = (string)jsonObject["token"];
var options = new RestClientOptions(uri)
{
MaxTimeout = -1,
};
var client = new RestClient(options);
var request = new RestRequest("/api/doc/upload/uploadFile2Doc", Method.Post);
request.AddHeader("appid", "CRM");
request.AddHeader("token", token);
request.AddHeader("userid", "zOumGpDpL6azXvv/DBS/V3wxmqRxkJg3G1iI20RKtks6PcPTEykqJBAgwze9xT4DSUnaMQdYev3BiAFEX1DpsFoDYKe5LYuXf8h0o/KD86HE4DqzlfrNhwr4bFrbT+YZrONxc+hzx8m1QsqdwZMosrPnSbM0xQEwwMr/TAg3JRQmgDEa+OggqYupEaVfVIJklJEdtX6g2Dfor+WX79aCnKphZxp/N62zi/w6iBusSbwtAADN8Ind61YBZq/+yoi9E/FlkENRTv3tTwNAA59CHYbYZnpvIEW7XddefPTx9JVWtPN40kueNBLTdbsz41HuHOIcMFdaEGTTnA6hYUWllg==");
request.AddHeader("Accept", "*/*"); request.AlwaysMultipartFormData = true;
request.AddFile("file", "./t.txt");
request.AddParameter("name", "t.txt");
RestResponse response = await client.ExecuteAsync(request); if (response.IsSuccessful)
{ Console.WriteLine("请求成功:");
Console.WriteLine(response.Content);
}
else
{
Console.WriteLine("请求失败:");
Console.WriteLine($"状态码: {response.StatusCode}");
Console.WriteLine($"错误信息: {response.ErrorMessage}");
Console.WriteLine($"响应内容: {response.Content}");
} async Task<string> GetToken()
{ var options = new RestClientOptions(uri)
{
MaxTimeout = -1,
};
var client = new RestClient(options);
var request = new RestRequest("/api/ec/dev/auth/applytoken", Method.Post);
request.AddHeader("appid", "CRM");
request.AddHeader("secret", "hqHTV4Bf0/AN74M+FXxWs3v2GxxYrQwGoE+ioUOkFttFAFMGAR55JAzDeUkxN5MUwkHy+ovu2Fh2NtEoQh396dIAkdUdHiqzvrxHAIaHPfNrcUtAFVkcqRAKOsVLBVSAR7tMTxw5KkEqYI4mV/pMZeZB5tKK08nUFOi5u06xUwB8AS/jo8CYfuAFJ8xAJWld6bjGnNW6nJXWXam1lbMsD9RUZWJ/RHSzrISDCmNauG+ejpNuB8A4uyAaY7kEIx723ZU2HkczExfQXxwtEjCwS8elj8bQp39j+g8bYlL2O6fP2GDlWhYhzorGgzNc6MYBZFaQ2vDgP3KCP9NX9JlhSQ==");
request.AddHeader("Accept", "*/*");
RestResponse response = await client.ExecuteAsync(request);
return response.Content;
}

PS:C#语法确实比JAVA写起来方便,psvm都没有就能用,而且比较有意思的是编译之后直接就能生成exe,之前我那JAVA写的东西想给别人直接双击启动 还得自己写bat,或者用exe4j,后面可以好好研究研究。

C#向JAVA发送form-data文件问题处理方案的更多相关文章

  1. fetch发送Form Data请求并携带cookie

    今天我们来说说如何fetch发送Form Data请求并携带cookie,直接进入正题好吧,别问我今天为啥不在开始吹两句了,累到一句牛逼不想吹...... 步骤1: 设置头部,"Conten ...

  2. VUE axios 发送 Form Data 格式数据请求

    axios 默认是 Payload 格式数据请求,但有时候后端接收参数要求必须是 Form Data 格式的,所以我们就得进行转换.Payload 和 Form Data 的主要设置是根据请求头的 C ...

  3. python 处理form/data文件上传

    处理multipart/form-data 的java serverlet请求接口通过python实现 记住不要在头加:"Content-Type":"multipart ...

  4. springMVC中对HTTP请求form data和request payload两种数据发送块的后台接收方式

    最近在做项目中发现,前台提交数据时,如果通过form表单提交和ajax发送json时,springMVC后台接收不能都通过@ModelAttribute方式处理,经过一番查找后,ajax发送json请 ...

  5. Socket通讯-C#客户端与Java服务端通讯(发送消息和文件)

    设计思路 使用websocket通信,客户端采用C#开发界面,服务端使用Java开发,最终实现Java服务端向C#客户端发送消息和文件,C#客户端实现语音广播的功能. Java服务端设计 packag ...

  6. [整理]Ajax Post请求下的Form Data和Request Payload

    Ajax Post请求下的Form Data和Request Payload 通常情况下,我们通过Post提交表单,以键值对的形式存储在请求体中.此时的reqeuest headers会有Conten ...

  7. html5 file upload and form data by ajax

    html5 file upload and form data by ajax 最近接了一个小活,在短时间内实现一个活动报名页面,其中遇到了文件上传. 我预期的效果是一次ajax post请求,然后在 ...

  8. form data和request payload的区别

    HTML <form> 标签的 enctype 属性 在下面的例子中,表单数据会在未编码的情况下进行发送: <form action="form_action.asp&qu ...

  9. Web 前沿——HTML5 Form Data 对象的使用

    XMLHttpRequest Level 2 添加了一个新的接口——FormData.利用 FormData 对象,我们可以通过 JavaScript 用一些键值对来模拟一系列表单控件,我们还可以使用 ...

  10. HTTP请求中的form data和request payload的区别

    HTML <form> 标签的 enctype 属性 在下面的例子中,表单数据会在未编码的情况下进行发送: <form action="form_action.asp&qu ...

随机推荐

  1. Fluent Builder 模式

    前言 以前最讨厌设计复杂方法调用, 就是那种需要一堆有逻辑规则的 config 作为参数的方法. 这种 config 通常是一个大对象, 有许多 property, property 之间有存在一些逻 ...

  2. Figma 学习笔记 – Plugin

    安装 Figma 安装 plugin 基本上就是点击一下开启而已. 到社区搜索 -> 点击 install Material Icon 下载地址 它的交互不是 drag 出来哦, 而是点击 ic ...

  3. 2024 年 C# 高效开发:精选实用类库

    前言 在平时开发中,好的类库能帮助我们快速实现功能,C#有很多封装好的类库. 本文将介绍一些2024年特别受欢迎的C#类库,并分析各自的优点让我们编程写代码变的更轻松.更快捷. 快来看一看有没有大家常 ...

  4. 《你必须掌握的Entity Framework 6.x与Core 2.0》代码下载

      https://item.jd.com/12376014.html<你必须掌握的Entity Framework 6.x与Core 2.0>代码下载,共享代码: https://git ...

  5. 一款基于Uniapp开发的开源低代码平台

    rtvue-lowcode低代码开发平台 rtvue-lowcode一款基于uniapp框架和uview组件库的低代码开发平台,项目提供可视化拖拽编辑器,采用MIT开源协议,适用于app.小程序等项目 ...

  6. foobar2000 v2.1.2 汉化版(更新日期: 2024.02.27)

    新春佳节,送上一份新年礼物,祝您在新的一年里,万事如意,心想事成,身体健康,事业有成,财源广进,家庭和睦,笑容常开,好运连连.     foobar2000 v2.1.2 汉化版 ---------- ...

  7. go 使用websocket

    package chat import ( "encoding/json" "github.com/gorilla/websocket" "githu ...

  8. js模拟二维数组求和

    JavaScri实际上没有二维数组的概念,但是由于js变量是松散的,所以能设置数组元素为数组来模拟二维数组,以此类推,可以模拟多维数组. /* 需求:模拟了3 * 3数组求右上三角元素之和1 + 3 ...

  9. signalR的身份认证

  10. Access to XMLHttpRequest at xxxx from origin xxx has been blocked by CORS policy: No 'Access-Control- Allow-Origin' header is present on the requested resource

    错误:控制台报错 : network 自动发起了请求: 解决办法: 找到 \node_modules\sockjs-client\dist\sockjs.js  文件 然后 crtl + g 快捷键跳 ...