Unsolved Question to file transfer via tcp with file name
-
Hello Guys,
once more I need the help of this forum.
I try to send file from a smartphone application to my computer.At the moment I get the information details via udp broadcast and then make a connection using tcp for the file transfer.
Thats how I send the information from my smartphone app.
void Communication::onSend() { mTcpSocket->connectToHost(mIpAddress, mTcpPort); if (mTcpSocket->waitForConnected(3000)) { qInfo() << "Connection estabished."; qDebug() << "Open File:" << mFileName; QFile file(mFileName); if (!file.open(QIODevice::ReadOnly)) { qWarning() << "Some error occur. Could not open the file."; return; } QByteArray block; QDataStream out(&block, QIODevice::WriteOnly); out << (quint64)0; out << file.readAll(); // out << (quint64)0 << file.fileName(); // QByteArray q = file.readAll(); block.append(q); out.device()->seek(0); out << (quint64)(block.size() - sizeof(quint64)); file.close(); mTcpSocket->write(block); mTcpSocket->waitForBytesWritten(); } else { qWarning() << "No connection established."; return; } }
And that is how I try to read the information.
void MyServer::readFromClient() { QDataStream in(mTcpSocket); QString fileName; ++mCounter; //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Try number 1, works but without the neccesary file name if (mRecievedSize == 0) { if (mTcpSocket->bytesAvailable() < (int)sizeof(quint16)) return; in >> mRecievedSize; } if (mTcpSocket->bytesAvailable() < mRecievedSize) return; QByteArray nextBytes; in >> nextBytes; currentBytes = nextBytes; QFile file(mFileName); if (file.open(QIODevice::WriteOnly)) { file.write(currentBytes); file.close(); } else { qWarning() << "Could not open the file."; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Try Number 2, doesent work if (mRecievedSize == 0) { if (mTcpSocket->bytesAvailable() < sizeof(quint64)) return; in >> mRecievedSize; } if (mTcpSocket->bytesAvailable() < mRecievedSize) return; in >> fileName; if (fileName != mFileName) mFileName = fileName; currentBytes = mTcpSocket->readAll(); QFile file(mFileName); if (file.open(QIODevice::WriteOnly)) { file.write(currentBytes); file.close(); } else { qWarning() << "Could not open the file."; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ qInfo() << "Method counter:" << mCounter; }
My question is what I have to change, so that I get the file name first to create the same file on my computer and after that I want to read the data and write it to the file.
Thanks for the help and greetings
Nils -
@Nils You need to define a protocol. First send the file name, then some special byte sequence and then the data from the file. On the receiver side you then would read the file name until this special byte sequence and afterwards the file data.
-
I tried two changes. First I used the two commented lines from the first code snippet to send the name of the file first. From the second code part I using the try number 2 to get the the name of the file.
I was a little surprised that it worked on the first try. But as I send a second file the method doesn't do what it should do. I get a new connection not more.
I checked the transfer with Wireshark and it seems that the packages are send and received bei the correct ip addresses.
But then nothing happens with it.@jsulm Thanks for your answer.
If I understand it correct, I have to use some kind of special characters between the file name and the data of the file and possible some kind of end sign at the end of the transfer.Please correct me if I'm wrong and feel free to give me a little hint or some kind of pseudo code.
-
@Nils I have one more idea :-)
On the server side you first write the length of the file name as 2byte int (unsigned short), then file name and then the file content. On the client side you first read 2 bytes (unsigned short, quint16) then n bytes (n is the number from those first 2 bytes), put those bytes into a string, then read the rest as file content. -
@jsulm
Thank you again for the fast reply.
In my application my Client is on my Smartphone an send the data to the server, on my laptop which then reads the data from the socket.
But I wil try it like you mention and let you know if it was successful or not. -
I try it out but it didn't do what I was hopping for.
So I changed my sender(Client side) to thisQByteArray block; QDataStream out(&block, QIODevice::WriteOnly); out << (quint16)mFileName.size(); out << mFileName; QByteArray q = file.readAll(); block.append(q); out.device()->seek(0); out << (quint64)(block.size() - sizeof(quint64)); file.close(); mTcpSocket->write(block); mTcpSocket->waitForBytesWritten();
and I try to receive it(server side) like this
if (mRecievedSize == 0) { if (mTcpSocket->bytesAvailable() < sizeof(quint16)) return; in >> mRecievedSize; } if (mTcpSocket->bytesAvailable() < mRecievedSize) return; fileName = mTcpSocket->read(mRecievedSize); mFileName = fileName; currentBytes = mTcpSocket->readAll(); QFile file(mFileName); if (file.open(QIODevice::WriteOnly)) { file.write(currentBytes); file.close(); } else { qWarning() << "Could not open the file."; }
I get the connection and my program do something. I also get this message "QFSFileEngine::open: No file name specified", but this is because I want to create a file without a proper file name.
What is wrong and where is my mistake in this?
-
@Nils I don't understand this part:
block.append(q); out.device()->seek(0); out << (quint64)(block.size() - sizeof(quint64));
Why do you seek and why not just:
block.append(q); out << block;
?
-
@jsulm
I looked at my code and it seems that I got two example mixed up.Here is the link. https://stackoverflow.com/questions/30288385/how-to-send-a-file-in-qt
So I changed a little bit in my code.
Her is the sender part.
void Communication::onSend() { mTcpSocket->connectToHost(mIpAddress, mTcpPort); if (mTcpSocket->waitForConnected(3000)) { qInfo() << "Connection estabished."; qDebug() << "Open File:" << mFileName; QFile file(mDataPath + "/" + mFileName); if (!file.open(QIODevice::ReadOnly)) { qWarning() << "Some error occur. Could not open the file."; return; } QFileInfo fileInfo(file); qInfo() << "Filename:" << mFileName << "; size:" << fileInfo.size(); QDataStream out(mTcpSocket); out << mFileName; out << QString::number(fileInfo.size()); while (!file.atEnd()) { QByteArray rawFile = file.read(5000); out << rawFile; mSize += rawFile.size(); qDebug() << "Send:" << mSize << "of:" << file.size(); qInfo() << rawFile; } } else { qWarning() << "No connection established."; return; } mTcpSocket->disconnectFromHost(); qDebug() << "Disconnected from the socket."; }
And this is my receiver part.
void MyServer::readFromClient() { QDataStream in(mTcpSocket); QString fileName; QString fileSize; QByteArray data; QFile file; ++mCounter; qInfo() << "readFromClient counter:" << mCounter; if (mCounter > 1000) { qWarning() << "Counter to high. Close connection."; mTcpSocket->close(); return; } if (mInfoRecieved) { mInfoRecieved = false; in >> fileName; qDebug() << "Recieved file name:" << fileName; in >> fileSize; qDebug() << "recieved file size:" << fileSize; if (!fileName.isEmpty()) { mFileName = fileName; } } file.setFileName(mFileName); if (file.open(QIODevice::Append)) { while (mTcpSocket->bytesAvailable()) { qDebug() << "Bytes available:" << mTcpSocket->bytesAvailable(); in >> data; qDebug() << data; file.write(data); } file.close(); } }
I let me output some information for the sender and the receiver.
The sender give me this.I SensorLogger: ../SensorLogger/src/communication.cpp:70 (void Communication::onSend()): Connection estabished. D SensorLogger: ../SensorLogger/src/communication.cpp:72 (void Communication::onSend()): Open File: "170906093258.xml" I SensorLogger: ../SensorLogger/src/communication.cpp:82 (void Communication::onSend()): Filename: "170906093258.xml" ; size: 127977 D SensorLogger: ../SensorLogger/src/communication.cpp:96 (void Communication::onSend()): Send: 5000 of: 127977 // Here is the output of the data so I can check if I have an error while reading the information from the file D SensorLogger: ../SensorLogger/src/communication.cpp:96 (void Communication::onSend()): Send: 10000 of: 127977 D SensorLogger: ../SensorLogger/src/communication.cpp:96 (void Communication::onSend()): Send: 15000 of: 127977 D SensorLogger: ../SensorLogger/src/communication.cpp:96 (void Communication::onSend()): Send: 20000 of: 127977 D SensorLogger: ../SensorLogger/src/communication.cpp:96 (void Communication::onSend()): Send: 25000 of: 127977 D SensorLogger: ../SensorLogger/src/communication.cpp:96 (void Communication::onSend()): Send: 30000 of: 127977 D SensorLogger: ../SensorLogger/src/communication.cpp:96 (void Communication::onSend()): Send: 35000 of: 127977 D SensorLogger: ../SensorLogger/src/communication.cpp:96 (void Communication::onSend()): Send: 40000 of: 127977 D SensorLogger: ../SensorLogger/src/communication.cpp:96 (void Communication::onSend()): Send: 45000 of: 127977 D SensorLogger: ../SensorLogger/src/communication.cpp:96 (void Communication::onSend()): Send: 50000 of: 127977 D SensorLogger: ../SensorLogger/src/communication.cpp:96 (void Communication::onSend()): Send: 55000 of: 127977 D SensorLogger: ../SensorLogger/src/communication.cpp:96 (void Communication::onSend()): Send: 65000 of: 127977
This is what I get from the receiver part.
we have a new connection! readFromClient counter: 1 Recieved file name: "170906093258.xml" recieved file size: "127977" Bytes available: 1396 "" readFromClient counter: 2 Bytes available: 1448 "" readFromClient counter: 3 Bytes available: 1448 "" readFromClient counter: 4 Bytes available: 1448 "" readFromClient counter: 5 Bytes available: 1448 "" readFromClient counter: 6 Bytes available: 1448 "" readFromClient counter: 7 Bytes available: 1448 "" readFromClient counter: 8 Bytes available: 1448 "" . . . readFromClient counter: 64 Bytes available: 1448 "" readFromClient counter: 65 Bytes available: 1448 "" readFromClient counter: 66 Bytes available: 1448 "" readFromClient counter: 67 Bytes available: 709 ""
I don't understand why the amount of byte read are so different from the amount I write to the socket.