前言

和上一篇文章一样,.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. CSS – vw, vh, position fixed and ICB (initial containing block)

    什么是 vw, vh? vh 的 v 指的是 viewport, h 就是 height. 它是 CSS 值的单位就像 px, %. .container { height: 30vh; backgr ...

  2. Navicat Premium 12的下载和安装

    首先下载navicate程序以及破解文件,这里一并存到了百度网盘直接下载即可 链接:https://pan.baidu.com/s/1a2QKHHUZ0ej1D78CjQ1ldA提取码:klus 解压 ...

  3. DQL—查询操作

    一.查询语法 select 字段列表 from 表名列表 where 条件列表 group by 分组列表 having 分组后条件 order by 排序字段 limit 分页限定 (提供一个表来操 ...

  4. Flutter 3.3 正式发布

    Flutter 3 是我们正式为全平台提供支持的一个重量级里程碑,距离它的发布仅过去了三个月,今天让我们有请 Flutter 3.3 正式版!近三个月我们并没有放慢更新迭代的速度--自 Flutter ...

  5. Flutter Web 近期的重要更新

    我们的发布重点优先关注在性能.开发者体验以及 Web 集成上 2021 年 3 月 Flutter Web 支持已进入稳定版,那么,下一步是什么? 我们对用户研究发现,有超过 10% 的 Flutte ...

  6. dotnet实现多态的三种方法

    虚方法 virual 抽象方法 abstract 不能 new  不带方法体: 接口 Interface

  7. 打包项目的时候出错 Multiple assets emit different content to the same filename index.html

    上一次的打包的时候 内存已存在 index.html 了所以冲突了 : 解决办法 :关机重启 : 或者改变当前的index.html 文件名称 :

  8. 有封装过v-model相关的双向绑定组件吗?

    有的,之前在做⼀个通⽤的上传组件的时候,⼀开始是通过传统的⽗⼦通信实现的,⽗传⼦实现的图⽚ 回显,⼦传⽗实现的图⽚url抛出传给给接⼝,后来使⽤v-model做了⼀点优化,简单了不少 追问: 具体是怎 ...

  9. 04 Transformer 中的位置编码的 Pytorch 实现

    1:10 点赞 16:00 我爱你 你爱我 1401 class PositionalEncoding(nn.Module): def __init__(self, dim, dropout, max ...

  10. Android复习(三)清单文件中的元素——>action、activity-alias、category、compatible-screens、data

    <action> 语法: <action android:name="string" />   包含于: <intent-filter> 说明: ...