C#向JAVA发送form-data文件问题处理方案
前言
和上一篇文章一样,.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文件问题处理方案的更多相关文章
- fetch发送Form Data请求并携带cookie
今天我们来说说如何fetch发送Form Data请求并携带cookie,直接进入正题好吧,别问我今天为啥不在开始吹两句了,累到一句牛逼不想吹...... 步骤1: 设置头部,"Conten ...
- VUE axios 发送 Form Data 格式数据请求
axios 默认是 Payload 格式数据请求,但有时候后端接收参数要求必须是 Form Data 格式的,所以我们就得进行转换.Payload 和 Form Data 的主要设置是根据请求头的 C ...
- python 处理form/data文件上传
处理multipart/form-data 的java serverlet请求接口通过python实现 记住不要在头加:"Content-Type":"multipart ...
- springMVC中对HTTP请求form data和request payload两种数据发送块的后台接收方式
最近在做项目中发现,前台提交数据时,如果通过form表单提交和ajax发送json时,springMVC后台接收不能都通过@ModelAttribute方式处理,经过一番查找后,ajax发送json请 ...
- Socket通讯-C#客户端与Java服务端通讯(发送消息和文件)
设计思路 使用websocket通信,客户端采用C#开发界面,服务端使用Java开发,最终实现Java服务端向C#客户端发送消息和文件,C#客户端实现语音广播的功能. Java服务端设计 packag ...
- [整理]Ajax Post请求下的Form Data和Request Payload
Ajax Post请求下的Form Data和Request Payload 通常情况下,我们通过Post提交表单,以键值对的形式存储在请求体中.此时的reqeuest headers会有Conten ...
- html5 file upload and form data by ajax
html5 file upload and form data by ajax 最近接了一个小活,在短时间内实现一个活动报名页面,其中遇到了文件上传. 我预期的效果是一次ajax post请求,然后在 ...
- form data和request payload的区别
HTML <form> 标签的 enctype 属性 在下面的例子中,表单数据会在未编码的情况下进行发送: <form action="form_action.asp&qu ...
- Web 前沿——HTML5 Form Data 对象的使用
XMLHttpRequest Level 2 添加了一个新的接口——FormData.利用 FormData 对象,我们可以通过 JavaScript 用一些键值对来模拟一系列表单控件,我们还可以使用 ...
- HTTP请求中的form data和request payload的区别
HTML <form> 标签的 enctype 属性 在下面的例子中,表单数据会在未编码的情况下进行发送: <form action="form_action.asp&qu ...
随机推荐
- SpringBoot——简介&&入门
SpringBoot 简介 SpringBoot是由Pivotal团队提供的全新框架,其设计目的是用来简化Spring应用的初始搭建以及开发过程 起步依赖 starter:SpringBoot中常见的 ...
- 用C#写个PDF批量合并工具简化日常工作
一. 前言 由于项目需要编写大量的材料,以及各种签字表格.文书等,最后以PDF作为材料交付的文档格式,过程文档时有变化或补充,故此处理PDF文档已经成为日常工作的一部分. 网上有各种PDF处理工具,总 ...
- 使用c++ onnxruntime构建项目出现的bug
bug1:The given version [11] is not supported, only version 1 to 7 is supported in this build. 应该是加载了 ...
- 批量读取nii文件的shape
import SimpleITK as sitk from glob import glob import os path = glob(r"D:\MyData\date\*") ...
- web端ant-design-vue Modal.info组件自定义icon和title使用小节
web端ant-design-vue Modal.info组件自定义icon和title整理小节,最近在项目中用到了自定义icon和title的功能,经过测试发现,如果自定义icon title会自动 ...
- 解决 WebSocketClient.js?5586:16 WebSocket connection to 'ws://192.168.13.25:8080/ws' failed:
控制台报错: vue.config.js Vue的配置文件 const { defineConfig } = require('@vue/cli-service') module.exports = ...
- 使用AVX2指令集加速推荐系统MMR层余弦相似度计算
原文:blog.fanscore.cn/a/62/ 1. 背景 前一段时间公司上线了一套Go实现的推荐系统,上线后发现MMR层虽然只有纯计算但耗时十分离谱,通过pprof定位问题所在之后进行了优化,虽 ...
- 使用nacos上传配置文件报错
1.使用nacos导入配置文件报错:未读取到合法数据,请检查导入的数据文件. 对比在naocs server中导出的文件,发现是少了一级目录.需要创建一个文件夹,名称为组的名称.因为在nacos上传文 ...
- 让查询可以使用 json path
记录一下最近sv.db的完善 1. 让查询可以使用 json path 有时候我们会存储 json 到 db,也有时会只取json部分数据,或者通过json部分数据进行过滤 所以sv.db 也支持这些 ...
- Oracle官方自动推荐大内存页脚本hugepages.sh
#!/bin/bash # # hugepages_settings.sh # # Linux bash script to compute values for the # recommended ...