【问题标题】:POST file upload works with curl but not with Qt (seafile web api)POST 文件上传适用于 curl 但不适用于 Qt (seafile web api)
【发布时间】:2014-06-02 14:02:58
【问题描述】:

我正在尝试使用 seafile web api (https://github.com/haiwen/seafile/wiki/Seafile-web-API#upload-file) 从 c++ Qt5 代码上传文件。

API 与 curl 配合得很好,但使用 Qt 我从 apache 收到“400 Bad Request”。

我使用了 wireshark 来查看请求中的差异。卷曲:

curl -k -F "file=@/tmp/test_up.txt; filename=qt.txt" -F parent_dir=/ myserver.com/seafhttp/upload-api/f8e70ecc

给我

POST /seafhttp/upload-api/f8e70ecc HTTP/1.1
User-Agent: curl/7.37.0
Host: myserver.com
Accept: */*
Content-Length: 292
Expect: 100-continue
Content-Type: multipart/form-data; boundary=------------------------9a2b257b2a34c31f

--------------------------9a2b257b2a34c31f
Content-Disposition: form-data; name="file"; filename="qt.txt"
Content-Type: text/plain

test up

--------------------------9a2b257b2a34c31f
Content-Disposition: form-data; name="parent_dir"

/
--------------------------9a2b257b2a34c31f--

现在是Qt源码:

QHttpMultiPart *multipart = new QHttpMultiPart(QHttpMultiPart::FormDataType);

QHttpPart file_part;
file_part.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"file\"; filename=\"qt.txt\"")); //
file_part.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain"));
QFile *file = new QFile{"/tmp/test_up.txt"};
file->open(QIODevice::ReadOnly);
file_part.setBodyDevice(file);
file->setParent(multipart); // we cannot delete the file now, so delete it with the multipart

QHttpPart parent_dir_part;
parent_dir_part.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"parent_dir\""));
parent_dir_part.setBody("/");

multipart->append(file_part);
multipart->append(parent_dir_part);

QNetworkRequest request{server + upload_url};
_reply = _manager.post(request, multipart);
multipart->setParent(_reply); // delete the multipart with the reply

给我

POST /seafhttp/upload-api/f8e70ecc HTTP/1.1
Content-Type: multipart/form-data; boundary="boundary_.oOo._MTgzMTcwMjYyNg==MTc3NDExNzExNg==NTI2MDQyOTI1"
MIME-Version: 1.0
Content-Length: 349
Connection: Keep-Alive
Accept-Encoding: gzip, deflate
Accept-Language: fr-FR,en,*
User-Agent: Mozilla/5.0
Host: myserver.com

--boundary_.oOo._MTgzMTcwMjYyNg==MTc3NDExNzExNg==NTI2MDQyOTI1
Content-Disposition: form-data; name="file"; filename="qt.txt"
Content-Type: text/plain

test up

--boundary_.oOo._MTgzMTcwMjYyNg==MTc3NDExNzExNg==NTI2MDQyOTI1
Content-Disposition: form-data; name="parent_dir"

/
--boundary_.oOo._MTgzMTcwMjYyNg==MTc3NDExNzExNg==NTI2MDQyOTI1--

服务器端我有两个请求的这些日志:

myserver.com - - [02/Jun/2014:15:20:18 +0200] "POST /seafhttp/upload-api/f8e70ecc HTTP/1.1" 200 166 "-" "curl/7.37.0"
myserver.com - - [02/Jun/2014:15:21:28 +0200] "POST /seafhttp/upload-api/f8e70ecc HTTP/1.1" 400 103 "-" "Mozilla/5.0"

现在这两个请求看起来非常接近,我在 Qt 代码中没有使用任何花哨的东西,遵循 QHttpMultiPart 文档示例。 我尝试更改 UserAgent 或边界以更接近 curl,但没有成功。

我在流量中提到的一个区别是,当我使用 curl 时,它会在发送其余数据之前等待“继续”:

[TCP segment of a reassembled PDU]
[ACK]
HTTP/1.1 100 Continue
[ACK]
[TCP segment of a reassembled PDU]
[ACK]
POST /seafhttp/upload-api/f8e70ecc HTTP/1.1  (text/plain)
[ACK]
HTTP/1.1 100 Continue
HTTP/1.1 200 OK

而 Qt 是这样的:

[TCP segment of a reassembled PDU]
[ACK]
POST /seafhttp/upload-api/f8e70ecc HTTP/1.1  (text/plain)
[ACK]
HTTP/1.1 400 Bad Request

这实际上不是我的主要域,所以我不确定我可以做些什么来进一步调试

感谢任何提示,谢谢

【问题讨论】:

    标签: c++ qt http curl network-programming


    【解决方案1】:

    好的,在手动重写请求直到它工作后,我找到了解决方案。这似乎是一个错误服务器端

    Qt 在标头中的边界声明周围添加双引号,这似乎尊重 rfc(请参阅此处已关闭的错误:https://bugreports.qt-project.org/browse/QTBUG-29744)。

    无论如何解决方法很简单,我只是重写了不带引号的标题:

    request.setRawHeader("Content-Type", "multipart/form-data; boundary=" + multipart->boundary());
    

    【讨论】:

    • 如果您满意,请随时接受您自己的答案。
    • @FinalContest 是的,这是实际的解决方案,但我必须等待接受
    猜你喜欢
    • 1970-01-01
    • 2015-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-06
    • 2011-03-09
    • 1970-01-01
    • 2018-09-17
    相关资源
    最近更新 更多