How to send a file in Qt?
10,037
Not so far i faced the same problem. So i find some solution. Test it on files about ~200Mb, no problems i see.
Sender part:
void FileSender::send()
{
QTcpSocket *socket = new QTcpSocket;
connect(socket, SIGNAL(disconnected()), socket, SLOT(deleteLater()));
// specified m_host and m_port to yours
socket->connectToHost(m_host, m_port);
socket->waitForConnected();
if ( (socket->state() != QAbstractSocket::ConnectedState) || (!m_file->open(QIODevice::ReadOnly)) ) {
qDebug() << "Socket can't connect or can't open file for transfer";
delete socket;
return;
}
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_5_4);
// This part i need to send not only file, but file name too
// Erase it if you needn't it
out << (quint32)0 << m_file->fileName();
QByteArray q = m_file->readAll();
block.append(q);
m_file->close();
out.device()->seek(0);
// This difference appear because of we send file name
out << (quint32)(block.size() - sizeof(quint32));
qint64 x = 0;
while (x < block.size()) {
qint64 y = socket->write(block);
x += y;
//qDebug() << x; // summary size you send, so you can check recieved and replied sizes
}
}
Server part:
I specified my server as :
class Server : public QTcpServer
{
Q_OBJECT
public:
explicit Server(QHostAddress host = QHostAddress::Any,
quint16 port = Constants::Server::DEFAULT_PORT,
QObject *parent = 0);
~Server();
public slots:
void start();
protected:
void incomingConnection(qintptr handle) Q_DECL_OVERRIDE;
private:
QHostAddress m_host;
quint16 m_port;
};
And realization:
Server::Server(QHostAddress host, quint16 port, QObject *parent)
: QTcpServer(parent),
m_host(host),
m_port(port)
{
...
// your settings init there
}
void Server::start()
{
if ( this->listen(m_host, m_port) )
qDebug() << "Server started at " << m_host.toString() << ":" << m_port;
else
qDebug() << "Can't start server";
}
void Server::incomingConnection(qintptr handle)
{
qDebug() << "incomingConnection = " << handle;
SocketThread *thread = new SocketThread(handle);
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
}
As you can see i create new class SocketThread
for receiving as multitheading server i need.
class SocketThread : public QThread
{
Q_OBJECT
public:
SocketThread(qintptr descriptor, QObject *parent = 0);
~SocketThread();
protected:
void run() Q_DECL_OVERRIDE;
signals:
void onFinishRecieved();
private slots:
void onReadyRead();
void onDisconnected();
private:
qintptr m_socketDescriptor;
QTcpSocket *m_socket;
qint32 m_blockSize;
};
SocketThread::SocketThread(qintptr descriptor, QObject *parent)
: QThread(parent),
m_socketDescriptor(descriptor),
m_blockSize(0)
{
}
SocketThread::~SocketThread()
{
delete m_socket;
}
void SocketThread::run()
{
m_socket = new QTcpSocket;
m_socket->setSocketDescriptor(m_socketDescriptor);
connect(m_socket, SIGNAL(readyRead()), this, SLOT(onReadyRead()), Qt::DirectConnection);
connect(m_socket, SIGNAL(disconnected()), this, SLOT(onDisconnected()), Qt::DirectConnection);
exec();
}
void SocketThread::onReadyRead()
{
QDataStream in(m_socket);
in.setVersion(QDataStream::Qt_5_4);
if (m_blockSize == 0) {
if (m_socket->bytesAvailable() < sizeof(quint32))
return;
in >> m_blockSize;
}
if (m_socket->bytesAvailable() < m_blockSize)
return;
QString fileName;
// get sending file name
in >> fileName;
QByteArray line = m_socket->readAll();
QString filePath = "YOUR"; // your file path for receiving
fileName = fileName.section("/", -1);
QFile target(filePath + "/" + fileName);
if (!target.open(QIODevice::WriteOnly)) {
qDebug() << "Can't open file for written";
return;
}
target.write(line);
target.close();
emit onFinishRecieved();
m_socket->disconnectFromHost();
}
void SocketThread::onDisconnected()
{
m_socket->close();
// leave event loop
quit();
}
I hope you will be able to adapt my code to your project. Best regards
Related videos on Youtube
Author by
Vlad
Updated on September 15, 2022Comments
-
Vlad over 1 year
I'm trying to send a file from client to server. But it sends only a part of file. Seems like it happens when the size of file is more than 2Mb. What can be the problem? Sorry if it's a stupid question but I can't find an answer in Google.
This is client cpp:
#include "widget.h" Widget::Widget(QWidget *parent) : QWidget(parent) { progressBar = new QProgressBar(this); tcpSocket = new QTcpSocket(this); fileLabel = new QLabel(this); progressLabel = new QLabel(this); fileBtn = new QPushButton(this); fileBtn->setText("Open"); sendBtn = new QPushButton(this); sendBtn->setText("Send"); layout = new QGridLayout; layout->addWidget(fileBtn, 0, 0); layout->addWidget(sendBtn, 0, 1); layout->addWidget(fileLabel, 1, 0); layout->addWidget(progressBar, 2, 0); connect(fileBtn, &QPushButton::clicked, this, &Widget::fileOpened); connect(sendBtn, &QPushButton::clicked, this, &Widget::onSend); setLayout(layout); } Widget::~Widget() { } void Widget::fileOpened() { fileName = QFileDialog::getOpenFileName(this, tr("Open file")); QFileInfo fileInfo(fileName); fileLabel->setText(fileInfo.fileName() + " : " + QString::number(fileInfo.size())); qDebug() << fileName; } void Widget::onSend() { tcpSocket->connectToHost("127.0.0.1", 33333); QFile file(fileName); QDataStream out(tcpSocket); int size = 0; if (file.open(QIODevice::ReadOnly)) { QFileInfo fileInfo(file); QString fileName(fileInfo.fileName()); out << fileName; qDebug() << fileName; out << QString::number(fileInfo.size()); qDebug() << fileInfo.size(); progressBar->setMaximum(fileInfo.size()); while (!file.atEnd()) { QByteArray rawFile; rawFile = file.read(5000); //false size inc QFileInfo rawFileInfo(rawFile); size += rawFileInfo.size(); out << rawFile; progressBar->setValue(rawFile.size()); qDebug() << QString::number(fileInfo.size()); qDebug() << "ToSend:"<< rawFile.size(); } out << "#END"; } }
This is a server one:
#include "myserver.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { startBtn = new QPushButton(this); startBtn->setText("Connect"); progressBar = new QProgressBar(this); layout = new QGridLayout; layout->addWidget(startBtn, 0, 0); layout->addWidget(progressBar, 1, 0); connect(startBtn, &QPushButton::clicked, this, &MainWindow::on_starting_clicked); setCentralWidget (new QWidget (this)); centralWidget()->setLayout(layout); } MainWindow::~MainWindow() { server_status=0; } void MainWindow::on_starting_clicked() { startBtn->setText("Connecting..."); tcpServer = new QTcpServer(this); connect(tcpServer, SIGNAL(newConnection()), this, SLOT(acceptConnection())); if (!tcpServer->listen(QHostAddress::Any, 33333) && server_status==0) { qDebug() << QObject::tr("Unable to start the server: %1.").arg(tcpServer->errorString()); } else { server_status=1; qDebug() << QString::fromUtf8("Сервер запущен!"); startBtn->setText("Running"); } } void MainWindow::acceptConnection() { qDebug() << QString::fromUtf8("У нас новое соединение!"); tcpServerConnection = tcpServer->nextPendingConnection(); connect(tcpServerConnection,SIGNAL(readyRead()),this, SLOT(slotReadClient())); // tcpServer->close(); QDir::setCurrent("/Users/vlad/Desktop/"); QString fileName; QString fileSize; } void MainWindow::slotReadClient() { QDataStream in(tcpServerConnection); QByteArray z; if (!isInfoGot) { isInfoGot = true; in >> fileName; qDebug() << fileName; in >> fileSize; qDebug() << fileSize; } QFile loadedFile(fileName); if (loadedFile.open(QIODevice::Append)) { while (tcpServerConnection->bytesAvailable()) { qDebug() << "bytesAvailable:" << tcpServerConnection->bytesAvailable(); in >> z; qDebug() << z; loadedFile.write(z); } loadedFile.close(); } }
-
Vlad almost 9 yearsgithub.com/ruspython/QtFileClient github.com/ruspython/QtFileServer I've uploaded projects on github, thanks for your reply
-
Vlad almost 9 yearsHello, thanks a lot for yout reply, could you send me the whole project, it would be a great example? I'm new in Qt, so it would be easier for me.
-
t3ft3l--i almost 9 yearsNo problem, here Github link. Described modules: Filesender at Agent-Win64, Server and SocketThread at Server-Win64
-
Vlad almost 9 yearsGood example, spasibo