使用 POST 上传大文件会冻结系统

Uploading big files with POST freezes the system

我有一个使用标准 post 请求将文件(视频文件)上传到服务器的应用程序,例如:

QNetworkRequest  request(QUrl("myUrl"));
QString bound="margin";
QByteArray data(QString("--"+bound+"\r\n").toLatin1());

data += "Content-Disposition: form-data; name=\"media_id\"\r\n\r\n";
data += id + "\r\n";
data += QString("--" + bound + "\r\n").toLatin1();

QString str = "Content-Disposition: form-data; name=\"file\"; filename=\"" + name + "\r\n";
data += str;
data += "Content-Type: video/mp4\r\n\r\n";

QFile f(path);
if(! f.open(QIODevice::ReadOnly))
{
    qDebug() << "uploadMediaRequest error opening " << path;
    return false;
}


QByteArray bytes;
bytes = f.readAll();

data.append(bytes);
data += "\r\n";
data += QString("--" + bound + "\r\n.").toLatin1();
data += "\r\n";

f.close();

request.setRawHeader(QString("Accept").toLatin1(),QString("application/json, text/javascript, */*; q=0.01").toLatin1());
request.setRawHeader(QString("Origin").toLatin1(),QString("http://dev.teamhood.io").toLatin1());
request.setRawHeader(QString("API-Client").toLatin1(),QString("desktop").toLatin1());
request.setRawHeader(QString("withCredentials").toLatin1(), QString("true").toLatin1());
request.setRawHeader(QString("Content-Type").toLatin1(),QString("multipart/form-data; boundary=" + bound).toLatin1());
request.setRawHeader(QString("Content-Length").toLatin1(), QString::number(data.length()).toLatin1());

然后 POST 该请求。 对于 1GB 或更少的文件,它工作得很好,但如果我尝试上传 1.5GB 的文件,我得到

myProgramName[948:32028] Communications error: <OS_xpc_error: <error: 0x7fff7c37bb60> { count = 1, contents =
"XPCErrorDescription" => <string: 0x7fff7c37bfa8> { length = 22, contents = "Connection interrupted" }}>
Got xpc error message: Connection interrupted

应用程序和 SO 冻死了。 我想我可以拆分大文件并将它们分成几部分上传并制作服务器 assemble 但我想知道你们中是否有人可以给我解释这个奇怪的错误。

我使用 OSX 和 Qt 5.4,提前谢谢!

由用户 Pavel Strakhov 解决:

QNetworkRequest request(QUrl("myUrl"));

QFile *f = new QFile(path);
if(! f->open(QIODevice::ReadOnly))
{
    qDebug() << "uploadMediaRequest error opening " << path;
    return false;
}

QHttpMultiPart * multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QHttpPart idPart, mediaPart;
idPart.setHeader(QNetworkRequest::ContentDispositionHeader,QVariant("form-data; name=\"media_id\""));
idPart.setBody(id.toLatin1());

mediaPart.setHeader(QNetworkRequest::ContentTypeHeader, type); 
mediaPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"file\"; filename=\""+ name + "\""));
mediaPart.setBodyDevice(f);
f->setParent(multiPart); 

multiPart->append(idPart);
multiPart->append(mediaPart);

request.setRawHeader(QString("Accept").toLatin1(),QString("application/json, text/javascript, */*; q=0.01").toLatin1());
request.setRawHeader(QString("Origin").toLatin1(),QString("http://dev.teamhood.io").toLatin1());
request.setRawHeader(QString("API-Client").toLatin1(),QString("desktop").toLatin1());
request.setRawHeader(QString("withCredentials").toLatin1(), QString("true").toLatin1());

networkManager->post(request, multiPart));

现在运行良好。