最近需要做上传文件操作。 由于历史原因,以前的接口使用了这样的入参:
代码如下:
/// <summary>
/// 上传文件
/// </summary>
[HttpPost]
public Result<UploadImageResult> UploadFile(byte[] bytes, string extName, string fromUri)
{
//业务代码
}
这个接口是一个POST请求的接口,调用接口之前,需要先将文件转换成文件流,再转换成byte数组的进行上传。
上传时调用此接口,然后返回这个文件的线上地址。
第一个入参是byte[]数组,第二、第三个入参是string类型的。
之前通过包装一层转发调用的,所以没有调用的实例。
最近需要通过Http直接调用,于是想了各种办法,但是一直报错:
415 Unsupported Media Type
各种测试期间,还报错过:
Unable to translate bytes [FF] at index 35 from specified code page to Unicode
参考了
1. c# - Post byte array to Web API server using HttpClient - Stack Overflow
2.
asp.net - Unable to translate bytes [FC] at index 35 from specified code page to Unicode - Stack Overflow
这些里面的方法,但是也没有解决。
尝试了各种改动,包括:
Content-Type 改为 application/octet-stream
Content-Type 改为 application/bson
Content-Type 改为 multipart/form-data
上面的改动也对应这Parameters的各种改动,都失败了。
还有这样的(失败案例,不过这是multipart/form-data传数据的正确用法):
byte[] fileBytes = new byte[] { 1, 2 };
string extName = "jpg";
string fromUri = "test";
var uploadUrl = "http://localhost:8101/Upload/UploadFile";
try
{
HttpClient InternalHttpClient = new HttpClient();
var strBoundary = DateTime.Now.Ticks.ToString("x"); //分隔符
var resultContent = new MultipartFormDataContent(strBoundary);
var fileByteArrayContent = new ByteArrayContent(fileBytes);
fileByteArrayContent.Headers.ContentType = new MediaTypeHeaderValue("application/x-jpg");
fileByteArrayContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") { Name = "bytes", FileName = "test.jpg" };
resultContent.Add(fileByteArrayContent);
var valueBytes1 = Encoding.UTF8.GetBytes(extName);
var byteArray1 = new ByteArrayContent(valueBytes1);
byteArray1.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") { Name = "extName" };
resultContent.Add(byteArray1);
var valueBytes2 = Encoding.UTF8.GetBytes(fromUri);
var byteArray2 = new ByteArrayContent(valueBytes2);
byteArray2.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") { Name = "fromUri" };
resultContent.Add(byteArray2);
var message = new HttpRequestMessage(HttpMethod.Post, uploadUrl);
message.Content = resultContent;
var responseMessage = InternalHttpClient.SendAsync(message).Result;
using (HttpContent ResponseBytes = responseMessage.Content)
{
var content = ResponseBytes.ReadAsStringAsync().Result;
}
}
catch (Exception ex)
{
string exstr = ex.Message;
}
上面这个失败的原因是:
bytes虽然我传输的是文件,但是bytes本身不是文件,所以不能把含有文件数据的bytes当做文件看,而是要把它当做一个json来看,只不过这个json是一个纯数字的json数组。
然后问了公司大佬,给我一个postman的调用示例,才知道原来自己的方向一直是错的。
由于上面的接口定义了三个参数,都没有经过类封装,所以这个接口直接就是三个参数的,接口默认是将bytes这个参数作为body主体的。 所以bytes传值时其实是json格式的一个body。
而extName和fromUri两个参数因为没有定义是什么参数类型,也没有封装到封装到类里,所以就作为url传值了。
所以在postman这样的工具传值时,应该是这样的:
这样传值,然后就成功了。
那么知道上面的原因之后,就比较好操作了
通过HttpClient请求是这样的:
byte[] fileBytes = new byte[] { 1, 2 };
string extName = "jpg";
string fromSource = "test";
var uploadUrl = "http://localhost:8101/Upload/UploadFile";
try
{
var newUrl = $"{uploadUrl}?extName={extName}&fromUri={fromUri}";
var client = new HttpClient();
HttpContent content = new StringContent(JsonConvert.SerializeObject(fileBytes));
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
HttpResponseMessage response = client.PostAsync(newUrl, content).Result;
response.EnsureSuccessStatusCode();
string con = response.Content.ReadAsStringAsync().Result;
}
catch (Exception ex)
{
string exstr = ex.Message;
}
通过RestClient请求是这样的:(需要引用RestSharp.dll)
byte[] fileBytes = new byte[] { 1, 2 };
string extName = "jpg";
string fromSource = "test";
var uploadUrl = "http://localhost:8101/Upload/UploadFile";
try
{
RestResponse Rsp;
var newUrl = $"{uploadUrl}?extName={extName}&fromUri={fromUri}";
using (var client = new RestClient(uploadUrl))
{
var Req = new RestRequest(newUrl, Method.Post);
Req.AddHeader("Content-Type", "application/json");
Req.AddBody(JsonConvert.SerializeObject(fileBytes));
Rsp = client.ExecuteAsync(Req).Result;
}
}
catch (Exception ex)
{
string exstr = ex.Message;
}
然后传值就成功了。
没找准问题所在,连搜答案都是错的。
要向正确的人问正确的问题,才能得到正确的答案。
一把辛酸泪,在此做个记录