使用libcurl上传文件

时间:2016-02-22 21:59:16

标签: c++ http post file-upload libcurl

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

所以基本上我正在访问某种类型的论坛,在那里可以发布消息,这些消息可以有附件。我的程序已经可以使用POST登录,阅读消息和发布短信到上面提到的表格就好了。唯一不起作用的是发布消息PLUS文件附件。

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

基本上,我正在尝试做的是使用libcurl使用相同的POST,我可以成功发布非附件消息,但是

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

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

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

我知道这对我试图访问的网站来说非常特别,可能没有人能够确切地知道服务器的期望。但是,任何人都可以给我一些可能出错的提示,或者通常会导致这种情况的原因吗? 有没有人可能知道一些虚拟网站,我至少可以用它来测试我的一般POST /上传功能,以验证我的libcurl用法是否正确?

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

- 更新3月12日:

正如daniel stenberg所说,我现在尝试使用multipart / formpost上传,但仍然没有成功。这就是详细输出给我的信息:

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);

1 个答案:

答案 0 :(得分:0)

没关系,我想我在multipart formdata中发送了错误的内容。使用CURLOPT_DEBUGFUNCTION添加调试输出并仔细检查并将输出与chrome的输出进行比较后,我发现与浏览器调用相比,filename参数的名称错误。
修复此问题后,我的上传工作正常。所以我上面的实现工作正确:)