将工作curl请求转换为HTTP

将工作curl请求转换为HTTP,http,curl,Http,Curl,我使用curl来执行POST请求,但我不能假设我的目标平台上有可用的curl,所以我尝试在HTTP中重写我的curl请求(这保证是可用的)。我对curl和HTTP的了解非常有限,所以我希望有人能指出我做错了什么 我的curl请求(命令行): curl输出的相关部分如下所示。这是在连接到服务器并向其发送POST请求之后。服务器现在让客户机知道可以发送第一个文件,curl首先通过发送文件自己的头,然后发送数据来响应(此处钳制) 发送数据,175字节(0xaf) 0000:--------------

我使用curl来执行POST请求,但我不能假设我的目标平台上有可用的curl,所以我尝试在HTTP中重写我的curl请求(这保证是可用的)。我对curl和HTTP的了解非常有限,所以我希望有人能指出我做错了什么

我的curl请求(命令行):

curl输出的相关部分如下所示。这是在连接到服务器并向其发送POST请求之后。服务器现在让客户机知道可以发送第一个文件,curl首先通过发送文件自己的头,然后发送数据来响应(此处钳制)

发送数据,175字节(0xaf)
0000:------------------------------------f2a4a742c08bf427
002c:内容配置:表单数据;name=“上传\u文件\u小转储”;菲尔
006c:ename=“UE4Minidump.dmp”
0085:内容类型:应用程序/八位字节流
公元00年:
=>发送数据,16384字节(0x4000)
0000:MDMP..a。。。。。。。m/S`………..;m/S`。。。。。。。。。。。。。。。。。。。。。。。。。;。。。。。。。。。。。。。。
0040:8Z……T……=…………`………8……….T。。
0080: .........\...........]..........= ..............................
00c0:aJ……`……Lw。。。。。。。。。。
0100:……T……?……i/S`。。。。。。
0140:G.M.T。S.t.a.n.d.a.r.d。T.i.m.e。。。。。。。。。。。。。。。。。。。
0180:G.M.T。D.a.y.l.i.g.h.t。T.i.m。
01c0:e..1.9.0.4.1。。。
等
通过阅读curl的详细输出,我创建了一个如下所示的HTTP请求(使用unreal engine 4库的c++代码):

TSharedRef-httpRequest=FHttpModule::Get().CreateRequest();
httpRequest->SetURL(文本(“https://xxxxxx.ingest.sentry.io/api/xxxxxx/minidump/?sentry_key=xxxxxxxxxxxxxxxxxxxxxxxx"));
httpRequest->SetVerb(文本(“POST”);
常量字符串边界(文本(“---------------------------f2a4a742c08bf427”);
httpRequest->SetHeader(文本(“内容类型”),文本(“多部分/表单数据;边界=”)+边界);
常量FString文件名(fpath::Combine(路径,crashToReport.folderName,文本(“UE4Minidump.dmp”));
确保(fpath::FileExists(fileName));
常量FString前缀边界(文本(“\r\n--”)+边界+文本(“\r\n”);
const FString fileHeader(文本(“内容处置:表单数据;名称=\”上传文件\小型转储\“;文件名=\”UE4Minidump.dmp\”\r\n内容类型:应用程序/八位字节流\r\n\r\n”);
FString文件内容;
FFILHELPER::LoadFileToString(文件内容,*文件名);
常量FString后缀边界(TEXT(“\r\n--”)+边界+TEXT(“--\r\n”);
常量FString内容(prefixBoundary+文件头+文件内容+后缀boundary);
httpRequest->SetContentAsString(内容);
这在一定程度上是可行的,服务器现在接受了这一点,并将接收文件-但是文件最终无法在服务器端读取,这让我觉得我没有以正确的格式发送它

多部分/表单数据请求中需要什么样的数据


我注意到,curl请求单独发送文件头(第一块175字节)。我很想知道如何做到这一点

我终于明白了。我不确定如何报告我做错了什么,但我认为这与在以下情况下发生的事情有关:

httpRequest->SetContentAsString(..)
,这可靠地导致后端无法解释我试图发送的二进制文件。我最终读取了二进制文件。。作为二进制文件:

TArray转储文件数据;
FFILHELPER::LoadFileToArray(dumpFileData,*fpath::Combine(路径,crashToReport.folderName,文本(“UE4Minidump.dmp”));
然后通过POST请求发送,与之前类似,但添加完整的表单数据部分作为二进制数据:

TSharedRef-httpRequest=FHttpModule::Get().CreateRequest();
httpRequest->SetURL(文本(“https://xxxxx.ingest.sentry.io/api/xxxxxx/minidump/?sentry_key=xxxxxxxxxxxxxxxxxxxxxxxxxxx"));
httpRequest->SetVerb(文本(“POST”);
常量字符串边界(文本(“---------------------------bb33b671b1212234”);
httpRequest->SetHeader(文本(“内容类型”),文本(“多部分/表单数据;边界=”)+边界);
httpRequest->SetHeader(文本(“接受”),文本(“*/*”);
httpRequest->SetHeader(文本(“Expect”)、文本(“100 continue”);
{
常量FString前缀边界(文本(“-”)+边界+文本(“\r\n”);
const FString fileHeader(文本(“内容处置:表单数据;名称=\”上传文件\小型转储\“;文件名=\”UE4Minidump.dmp\”\n内容类型:应用程序/八位字节流\r\n\r\n”);
常量FString后缀边界(TEXT(“\r\n--”)+边界+TEXT(“--\r\n”);
焦油含量;
Append(FStringToUint8(prefixBoundary+fileHeader));
CombinedContent.Append(dumpFileData);
Append(FStringToUint8(后缀边界));
httpRequest->SetContent(组合内容);
}
httpRequest->ProcessRequest();
为完整起见,FStringToUint8定义如下:
//将FString转换为UTF8并将其放入TArray中
TArray FStringToUint8(常数FString&InString)
{
TArray输出字节;
//处理空字符串
如果(InString.Len()>0)
{
FTCHARTOUF8已转换(*指令);//转换为UTF8
Append(reinterpret_cast(Converted.Get()),Converted.Length());
}
返回OutBytes;
}

您需要的是一个表单帖子,而不是带有base64编码文件的JSON,请参见示例(不确定该实现是否正确,但需要一个一般性提示)。感谢您的建议,很遗憾我尝试了这一点,具有讽刺意味的是,最后一篇帖子建议使用JSON。这就是我被卡住的地方。这完全取决于你发布到的端点支持什么。如果它同时支持这两种格式,那么两者都可以,如果它只接受一个表单post,那么您需要发送一个合适的表单post,而JSON将不起作用。因此,假设您的端点需要一个表单post,并构建它;您的问题将显示代码以及运行代码时会发生什么。@CodeCaster经过大量测试后,我已使用一些新信息更新了我的问题
<= Recv header, 23 bytes (0x17)
0000: HTTP/1.1 100 Continue
=> Send data, 175 bytes (0xaf)
0000: --------------------------f2a4a742c08bf427
002c: Content-Disposition: form-data; name="upload_file_minidump"; fil
006c: ename="UE4Minidump.dmp"
0085: Content-Type: application/octet-stream
00ad: 
=> Send data, 16384 bytes (0x4000)
0000: MDMP..a..... .......m/S`.........................;..............
0040: 8Z......T...=...........`.......8...........T................[..
0080: .........\...........]..........= ..............................
00c0: ....................................aJ.......`......Lw..........
0100: ............T........?..i/S`........ ... ... ............ ......
0140: ............G.M.T. .S.t.a.n.d.a.r.d. .T.i.m.e...................
0180: ................................G.M.T. .D.a.y.l.i.g.h.t. .T.i.m.
01c0: e...................................................1.9.0.4.1...
..etc..
TSharedRef<IHttpRequest, ESPMode::ThreadSafe> httpRequest = FHttpModule::Get().CreateRequest();
    
httpRequest->SetURL(TEXT("https://xxxxxx.ingest.sentry.io/api/xxxxxx/minidump/?sentry_key=xxxxxxxxxxxxxxxxxxxxxxxx"));

httpRequest->SetVerb(TEXT("POST"));
const FString boundary(TEXT("------------------------f2a4a742c08bf427"));
httpRequest->SetHeader(TEXT("Content-Type"), TEXT("multipart/form-data; boundary=") + boundary);

const FString fileName(FPaths::Combine(path, crashToReport.folderName, TEXT("UE4Minidump.dmp")));

ensure(FPaths::FileExists(fileName));

const FString prefixBoundary(TEXT("\r\n--") + boundary + TEXT("\r\n"));
const FString fileHeader(TEXT("Content-Disposition: form-data; name=\"upload_file_minidump\"; filename=\"UE4Minidump.dmp\"\r\nContent-Type: application/octet-stream\r\n\r\n"));

FString fileContents;
FFileHelper::LoadFileToString(fileContents, *fileName);

const FString suffixBoundary(TEXT("\r\n--") + boundary + TEXT("--\r\n"));

const FString content(prefixBoundary + fileHeader + fileContents + suffixBoundary);
httpRequest->SetContentAsString(content);
httpRequest->SetContentAsString(..)