How to send a file along with its filename over QTCPSocket?
Asked Answered
T

2

5

Is there any simple way to send a file to server with the filename included so that the filename in server and client are exactly the same?

Here is my code

Sender

QString path = QApplication::applicationDirPath()+"/belajardansa.bmp";
QFile inputFile(path);
QByteArray read ;
inputFile.open(QIODevice::ReadOnly);
while(1)
{
    read.clear();
    read = inputFile.read(32768*8);
    qDebug() << "Read : " << read.size();
    if(read.size()==0)
       break;
    qDebug() << "Written : " << socket->write(read);
    socket->waitForBytesWritten();
    read.clear();
}
inputFile.close();

Receiver

QTcpSocket* socket = static_cast<QTcpSocket*>(sender());
QBuffer* buffer = buffers.value(socket);

QByteArray read = socket->read(socket->bytesAvailable());
qDebug() << "Read : " << read.size();

QFile file(  ???); // what should I put in the bracket???
if(!(file.open(QIODevice::Append)))
{
    qDebug("File cannot be opened.");
    exit(0);
}
file.write(read);
file.close();
Tipcat answered 10/12, 2012 at 12:9 Comment(0)
V
6
  1. You can create your own data structure that will represent file contents and its file name and convert it to QByteArray and vice versa.

  2. You can send two requests: the first with the file name and the second with data.

Valora answered 10/12, 2012 at 13:12 Comment(1)
Thank you for your respond Hank, your first suggestion is a little complicated for me as I am a newbie in C++ and Qt. Can you give me a sample code to convert a data structure to QByteArray? about your second suggestion, How to case the socket data so the server can recognize if the socket data contain a filename or data.Tipcat
A
6

There is no really simple way. You have to create your own protocol. However, that protocol can often be very very simple protocol.

On writing end, simple example

  1. Convert QString filename to QByteArray using QString::toUtf8()
  2. Write to socket the length of QByteArray as binary int
  3. Write to socket the bytes from the QByteArray containing the file name
  4. Write to socket the length of file as binary int
  5. Write to socket the bytes from the file
  6. Close

On reading end:

  1. Read integer telling length of file name
  2. Read that many bytes to a QByteArray
  3. Convert file name from QByteArray to QString using QString::fromUtf8()
  4. Read integer telling length of data
  5. Keep reading bytes and writing the to file until you got that many bytes
  6. Close

When writing and reading, if you want to communicate between different computers, you should convert the into network byte order before writing, and back to host byte order after reading. You could also decide to define, that you use "x86 byte ordering", and anybody reading the data with different CPU needs to convert...

Annoy answered 10/12, 2012 at 13:34 Comment(3)
thank you for your respond hyde, your suggestion seems very useful to try. But there is one problem for me as a newbie. How to case the incoming socket data so that I can put the data to the right step in that protocol. (As we know that in TCP written data sent in some packages.)Tipcat
TCP/IP is a stream protocol, you write and read bytes, not packets. It also guarantees order and transmission of all bytes. So you can trust you will get exact same bytes in exact same order (or you get error and disconnection). That's also why you must write your own "packet sizes" to the socket, because TCP/IP does not give you packets with a size, just stream of bytes.Annoy
And one more clarification: you can of course write and read data many bytes at a time, as is evident from the methods you use when writing and reading. It's just that sizes of your writes are lost, receiver does not know if you wrote for example 10 and then 100 bytes, or if you wrote 110 bytes all at once.Annoy

© 2022 - 2024 — McMap. All rights reserved.