Sending Large file over QTcpSocket
-
@JonB that is why i suggested upload as the first solution because it uses a boundary at the beginning
@SlayH this is an exemple for uploading an image and textQHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QHttpPart textPart;
textPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name="text""));
textPart.setBody("my text");QHttpPart imagePart;
imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg"));
imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name="image""));
QFile *file = new QFile("image.jpg");
file->open(QIODevice::ReadOnly);
imagePart.setBodyDevice(file);
file->setParent(multiPart); // we cannot delete the file now, so delete it with the multiPartmultiPart->append(textPart);
multiPart->append(imagePart);QUrl url("http://my.server.tld");
QNetworkRequest request(url);QNetworkAccessManager manager;
QNetworkReply *reply = manager.post(request, multiPart);
multiPart->setParent(reply); // delete the multiPart with the reply -
@SlayH said in Sending Large file over QTcpSocket:
with an end file marker
How are you going to do that when sending packets which contain any pattern of binary bytes read from a file? I think you will need to precede by a byte count (or packet count or some kind of "special/empty" packet at the endif you really wish, but as I said I don't think your packet-ization achieves anything at all or what you might think it achieves).
Also, as I said earlier. I assume your
ready_read()
is (supposed to be) a slot forreadyRead()
signal? Then as long as you have a pattern likewhile (_socket->bytesAvailable()) data << _socket->readAll();
and assume (as you do) that
data
will be some kind of "complete set of data or packets" then your algorithm is fatally flawed. Might work for a bit/some cases, might not. You are assuming a relationship which does not exist, such as that for each_socket->write(packet)
you will receive some single read, which is not at all true. This is partly why giving up on packets and just sending a byte count followed by a stream of binary bytes would be simpler. -
@Ronel_qtmaster
What makes you think the OP has any kind of HTTP server here? I don't see that he has indicated any such thing? -
@JonB it is just an exemple.If he has a QTcpServer listening to 127.0.01 and port 455 for exemple, he can change the url to QUrl("Http://127.0.0.1:455"), which will reach the tcpserver listening
-
@Ronel_qtmaster
And thisQTcpServer
will be able to service HTTP requests, so that you can send your file withQHttpMultiPart
which is what you are advocating? Without anyQ[Abstract]HttpServer
? I must be misunderstanding something then. -
@JonB Yeah ready_read() is a slot for readyRead(). I did think that for each _socket->write(packet) there will be an emitted signal for readRead() but You told me it isn't the case.``` If I am supposed to send a byte count followed by a stream of binary bytes, how would it be then ???
code_text -
@SlayH said in Sending Large file over QTcpSocket:
I did think that for each _socket->write(packet) there will be an emitted signal for readRead()
That's what I tried to say at the outset, because so many people assume it. It is not the case, at all sorts of levels in the handling.
I'm not going to write full code. In outline all you have to do is
int size = ...; sendsocket->write(&size, sizeof(size)); sendsocket->write(fileContent, size);
at sender side.
At receiver side, read that initial
size
and then keep writing received bytes to file till that many bytes have been read. All reads go throughonReadyRead
slot, but you can only assume that will receive 1 or more bytes any time it's called. You need to receive at leastsizeof(size)
bytes (allow for accumulating that many bytes over multiple calls toonReadyRead()
in e.g. a class member buffer), all subsequent bytes can go to output file counting up/down to that many.You may want to think about how to send that
int
(do you care about byte-order for cross-platform?). You may findQDataStream
's Using Read Transactions useful if you don't want to write your own stuff. (You may only want to use that for the leadingint
. For the "potentially large" amount of data which follows for the file content you will not want to read all of that into memory/a variable, rather only "chunks" at a time from whatever happens to have arrived there, immediately copied out to destination file.) -
Hi,
Since you are using QDataStream, you can use transactions.
-
@JonB Yes exactly.The only thing is that he will have to remove the request headers from the sent packet, and put the original data in a file.
In a nutshell, when sending files with upload, the request headers are sent with the file data.You just need to separate both and keep the essential part