使用 libcurl 上传文件

Use libcurl to upload a file

本文关键字:文件 libcurl 使用      更新时间:2023-10-16

我正在尝试使用libcurl访问网站,并发布到包含文件上传的表单中。我不是100%确定我在做什么,因为我基本上是使用chrome开发人员工具对网站进行逆向工程并分析POST/GET调用,然后我将使用libcurl进行复制。

所以基本上我正在访问某种论坛,人们可以在其中发布消息,其中可以有一个附件。我的程序已经可以使用 POST 登录、阅读消息和将文本消息发布到上述表单中。唯一不起作用的是发布消息PLUS文件附件。

根据chrome开发人员工具,当我使用浏览器上传文件时,我只能看到相同表单的POST,包括更多参数(文件名,文件上传标志)。但是,我在 chrome 开发人员工具中看不到任何文件上传的迹象,因此我没有关于如何以编程方式执行此操作的提示。

基本上,我只是想做的是使用相同的 POST 使用我可以成功用于发布非附件消息libcurl,但是

  • 我将包括额外的后置参数
  • libcurl提供读取功能
  • 告诉libcurl上传 ( CURLOPT_UPLOAD
  • 供应CURLOPT_INFILESIZE
  • 我还试图额外提供CURLOPT_POST

现在,成功的 POST(不带附件)将始终重定向到概述,因此 HTTP 302 表示操作成功。
但是,一旦我尝试使用上面的代码上传,我只会得到HTTP 200并且不会发送消息。然而,我可以看到我的读取函数被调用,并且文件的所有字节都被传输了。

有趣的是,当我省略CURLOPT_UPLOAD时,我可以看到我的读取函数没有被调用(因此没有传输文件),并且 POST 将获得 HTTP 302 作为回复,并且消息实际上是发布的。但是,当您查看它时,它包含一个提示"附件已删除"。

我知道所有这些对于我试图访问的网站来说都非常特别,可能没有人能确切地知道服务器的期望。但是谁能给我一些提示,说明可能出了什么问题,或者通常是什么导致了这种情况?
有没有人可能知道一些虚拟站点,我至少可以用来测试我的一般 POST/上传功能,以验证我的libcurl使用是否正确?

任何提示/提示非常感谢:)


- 3月12日更新:


正如丹尼尔·斯坦伯格(Daniel Stenberg)所建议的那样,我现在正在尝试使用多部分/表单帖子上传,但仍然没有成功。这就是详细输出给我的:

16/03/12 23:21:04 [HTTP] POST http://www.some.url // printed by my lib
* Found bundle for host www.some.url: 0x154f53460
* Re-using existing connection! (#1) with host www.some.url
* Connected to www.some.url (someipaddress) port 80 (#1)
> POST /some/path/ HTTP/1.1
Host: www.some.url
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:22.0)         Gecko/20100101 Firefox/22.0
Accept: */*
Cookie: FUP_sid=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;             FUP_vid=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;     FUPautologin=cb8c3ef4fcdecc390f6eca3f37814f623431219
Content-Length: 170627
Expect: 100-continue
Content-Type: multipart/form-data; boundary=------------------------1b0a4317b11b7518
< HTTP/1.1 100 Continue

几秒钟暂停/上传在这里

< HTTP/1.1 302 Found
< Date: Sat, 12 Mar 2016 22:21:04 GMT
< Server: Apache
< Cache-Control: private, proxy-revalidate, s-maxage=0, no-cache
< X-XSS-Protection: 1; mode=block
< X-Frame-Options: SAMEORIGIN
< Location: http://www.some.url/some/path/redirect/
< Vary: Accept-Encoding
< Transfer-Encoding: chunked
< Content-Type: text/html; charset=UTF-8
* HTTP error before end of send, stop sending
< 
* Closing connection 1
16/03/12 23:21:06 [HTTP] DONE (0/302)    // printed by my lib, http code of last operation

我可以使用相同的libcurl代码成功将文件上传到 posttestserver.com,所以我不确定问题是什么。最让我困惑的是* HTTP error before end of send, stop sending的说法。似乎服务器以某种方式中止/拒绝上传。在网站上,我可以看到我提交的消息,并提示上传的文件已被删除(或从未完全上传?

可能是libcurl对来自服务器的 302 响应感到困惑(这是新消息提交的正常响应,因为它重定向到消息概述),或者可能是什么问题?

请帮忙:(

这是我的代码:

struct curl_httppost* postForm = NULL;
struct curl_httppost* last = NULL;
for (HtmlInput* param= form->getFirstParameter(); param;
     param= form->getNextParameter())
{
  HtmlElement::Attribute* nameAtt= param->getAttribute("name");
  HtmlElement::Attribute* valueAtt= param->getAttribute("value");
  curl_formadd(&postForm, &last,
               CURLFORM_COPYNAME,     notNull(nameAtt ? nameAtt->value.c_str() : 0),
               CURLFORM_COPYCONTENTS, notNull(valueAtt ? valueAtt->value.c_str() : 0),
               CURLFORM_END);
}
if (attachment)
{
  curl_formadd(&postForm, &last,
               CURLFORM_COPYNAME, "name",
               CURLFORM_BUFFER, attachmentName ? attachmentName : "fileupload",
               CURLFORM_BUFFERPTR, uploadBuffer.buffer,
               CURLFORM_BUFFERLENGTH, uploadBuffer.size,
               CURLFORM_CONTENTTYPE, contentType,
               CURLFORM_END);
}
curl_easy_setopt(session, CURLOPT_URL, url);
curl_easy_setopt(session, CURLOPT_HTTPPOST, formpost);
curl_easy_setopt(session, CURLOPT_VERBOSE, 1L);
CURLcode curlCode= curl_easy_perform(session);

关系,我想我在多部分表单数据中发送了错误的内容。在添加带有CURLOPT_DEBUGFUNCTION的调试输出并仔细检查输出并将其与chrome的输出进行比较后,我发现与浏览器调用相比,文件名参数的名称错误。
解决此问题后,我的上传工作正常。所以我上面的实现是有效的,并且是正确的:)