.NET Core HttpClient调用腾讯云对象存储Web API的"ERROR_CGI_PARAM_NO_SUCH_OP"问题
开门见山地说一下问题的原因:调用 web api 时请求头中多了双引号,请求体中少了双引号。
腾讯云提供的对象存储(COS)C# SDK 是基于 .NET Framework 用 WebRequest 实现的,我们直接将这个实现迁移到 .NET Core 是可以正常调用,但后来我们基于 HttpClient 实现,调用 web api 时总是返回 "ERROR_CGI_PARAM_NO_SUCH_OP" 错误。
用 Wireshark 抓包后发现,基于 WebRequest 的实现的请求包开头比基于 HttpClient 的实现多了个 "Preamble: 0d0a"。
1)基于 WebRequest 的实现

2)基于 HttpClient 的实现

检查代码后发现,在构建 multipart/form-data 时,腾讯云官方基于 WebRequest 的实现是这样构建数据包的开头的:
var boundary = "---------------" + DateTime.Now.Ticks.ToString("x");
var beginBoundary = Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
我们基于 HttpClient 的实现用的是 MultipartFormDataContent :
var boundary = "---------------" + DateTime.Now.Ticks.ToString("x");
var data = new MultipartFormDataContent(boundary);
前者构建的 Multipart 数据包比后者多出了 \r\n (回车换行),而 0d0a 正是 \r\n 的 ASCII 码。根据 Multipart Content-Type 规范,这个多出来的 \r\n 是多余的,所以被解析为 "Preamble: 0d0a" 。
于是修改基于 HttpClient 的实现,也加上这个额外的 \r\n :
var ms = new MemoryStream();
var bytes = Encoding.UTF8.GetBytes("\r\n");
ms.Write(bytes, , bytes.Length);
(await data.ReadAsStreamAsync()).CopyTo(ms);
ms.Position = ;
var sc = new StreamContent(ms);
sc.Headers.ContentType = data.Headers.ContentType;
request.Content = sc;
但加上后依然是"ERROR_CGI_PARAM_NO_SUCH_OP"错误(实际上不加开头的 \r\n 也没关系,问题与这个无关)。
继续仔细对比抓包,发现 HttpClient 的实现中 form-data 部署少了双引号,比如 name=op ,基于 WebRequest 的实现用的是 name="op"

但加上后依旧是"ERROR_CGI_PARAM_NO_SUCH_OP"错误。
再继续对比抓包,发现 HttpClient 的实现这 Content-Type 中比 WebRequest 的实现多了2个双引号
1) Content-Type: multipart/form-data; boundary="---------------8d5289300ea3a0d"
2) Content-Type: multipart/form-data; boundary=---------------8d527aeed341201
去找这2个双引号之后,问题终于解决了。
最终基于 .NET Core HttpClient 的实现代码如下("Preamble: 0d0a"没有影响,不需要加):
var request = new HttpRequestMessage(HttpMethod.Post, url);
request.Headers.Authorization = new AuthenticationHeaderValue("Authorization", signature); var boundary = "---------------" + DateTime.Now.Ticks.ToString("x");
var data = new MultipartFormDataContent(boundary);
data.Add(new ByteArrayContent(Encoding.UTF8.GetBytes("upload")), "\"op\""); var streamContent = new StreamContent(uploadStream);
streamContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "\"fileContent\"",
FileName = "\"" + fileName + "\""
};
streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
data.Add(streamContent); data.Headers.Remove("Content-Type");
data.Headers.Add("Content-Type", "multipart/form-data; boundary=" + boundary);
request.Content = data;
var response = await _httpClient.SendAsync(request);
var json = await response.Content.ReadAsStringAsync();
.NET Core HttpClient调用腾讯云对象存储Web API的"ERROR_CGI_PARAM_NO_SUCH_OP"问题的更多相关文章
- php 腾讯云 对象存储V5版本 获取返回的上传文件的链接方法
腾讯云 对象存储V5版本 文档地址:https://github.com/tencentyun/cos-php-sdk-v5 调用简单文件上传方法: 返回数据如下 Array ( [data:prot ...
- Laravel项目使用腾讯云对象存储上传图片(cos-php-sdk-v5版本)
为了加快网站访问速度.降低网站负载,现在越来越多的网站选择把图片等静态文件放在云上,这里介绍一下腾讯云对象存储在Laravel项目中的使用 1.申请腾讯云对象存储.创建Bucket.获取APPID等参 ...
- 微信小程序基于腾讯云对象存储的图片上传
在使用腾讯云对象存储之前,公司一直使用的是传统的FTP的上传模式,而随着用户量的不断增加,FTP所暴露出来的问题也越来越多,1.传输效率低,上传速度慢.2.时常有上传其他文件来攻击服务器,安全上得不到 ...
- Docsify+腾讯云对象存储 COS,一键搭建云上静态博客
最近一直在想如何利用 COS 简化静态博客的搭建过程.搜了很多的静态博客搭建过程,发现大部分的静态博客都要通过编译才能生成静态页面.功夫不负有心人,终于让我找到了一个超简洁博客的搭建方法. 效果预览 ...
- 腾讯云--对象存储cos绑定自定义域名
1.登录腾讯云控制台,找到对象存储一栏 2.选择一个你想绑定域名的存储桶 3.进入你选择的存储桶,点击域名管理 4.选择自定义源站域名.在域名处填写你要设置的自定义域名,在源站类型处选择静态网站源站, ...
- 腾讯云对象存储COS新品发布——智能分层存储,自动优化您的存储成本
近日,腾讯云正式发布对象存储新品--智能分层存储,能够根据用户数据的访问模式,自动地转换数据的冷热层级,为用户提供与标准存储一致的低延迟和高吞吐的产品体验,同时具有更低的存储成本. 熟悉数据存储的用户 ...
- Python调用腾讯云API,实现人脸年龄变化
网上看到了一个教程,调用腾讯云的人脸识别api和修改年龄api来实现模拟人物不同年龄的面貌 但是大多数教程的代码都是想同的,估计是抄袭哪个人的关键是执行不了 刚好周杰伦马上要发新专辑了,小改一下,拿杰 ...
- 谈谈调用腾讯云【OCR-通用印刷体识别】Api踩的坑
一.写在前面 最近做项目需要用到识别图片中文字的功能,本来用的Tesseract这个写的,不过效果不是很理想. 随后上网搜了一下OCR接口,就准备使用腾讯云.百度的OCR接口试一下效果.不过这个腾讯云 ...
- C# 调用腾讯云接口获取视频基本信息
做项目需要上传视频,获取时长,上传教程很多,获取信息很少,官方只有一条请求地址. 找了好久,都没有说这个请求地址怎么用.最后发现需要调用腾讯云SDK 官方地址:https://github.com/Q ...
随机推荐
- js 学习
{% load static %} <!DOCTYPE html> <html lang="en"> <head> <meta chars ...
- CentOS 7 配置HTTPS加密访问SVN
上一篇文章已经介绍了如何在CentOS7环境下安装SVN并整合HTTP访问 http://www.cnblogs.com/fjping0606/p/7581093.html 那么本文则介绍如何添加HT ...
- Shell函数的7种用法介绍
1. 在shell文件内部定义函数并引用: 复制代码代码如下: [~/shell/function]# cat factorial.sh #!/bin/bashfunction factorial{f ...
- 【R作图】蜜蜂群图beeswarm和jitter的使用
最近经常要画好看的盒形图,还要在上面加入散点,所以总结了两个方法. 第一种方法是,利用beeswarm函数: library(beeswarm) beeswarm 蜜蜂群图 http://rgm3.l ...
- 0x02 Spring Cloud 学习文档
每个Spring项目都有自己的; 它详细解释了如何使用项目功能以及使用它们可以实现的功能. Spring Cloud 版本 参考文档 API文档 Finchley SR2 CURRENT GA Ref ...
- Adam算法
结合了Momentum 和RMSprop算法的优点
- ios UIButton设置高亮状态下的背景色
一,通过按钮的事件来设置背景色 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 - (void)viewDidLoad { [ ...
- Redis介绍以及安装(Linux)
Redis介绍以及安装(Linux) redis是当前比较热门的NOSQL系统之一,它是一个key-value存储系统.和Memcached类似,但很大程度补偿了memcached的不足,它支持存储的 ...
- Zookeeper系列三:Zookeeper客户端的使用(Zookeeper原生API如何进行调用、ZKClient、Curator)和Zookeeper会话
一.Zookeeper原生API如何进行调用 准备工作: 首先在新建一个maven项目ZK-Demo,然后在pom.xml里面引入zk的依赖 <dependency> <groupI ...
- JConsole & JVisualVM远程监视Websphere服务器JVM的配置方法
原文链接:http://xjsunjie.blog.51cto.com/999372/1331880/ jconsole是JDK里自带的一个工具,可以监测Java程序运行时所有对象的申请.释放等动作, ...