Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to send a File with Qt



  • Hello Everyone,

    First of all i want to thank the Qt Community for the great Content of this forum. I'm a Qt newbie and I'm working on a little Qt Application that transfers one File from my Computer to another Computer.

    I did some research and ended up writing this Code

    Client::Client(QObject *parent) :
    	QObject(parent)
    {
    }
    
    void Client::Upload()
    {
    	
    	QString ZFsolutionFolder = "C:\\Users\\X240\\Desktop\\Masterarbeit\\ZF-Schulungssystem\\ZF-Schulungssystem\\TwinCAT\\";
    	QString ZFsolutionName = "TwinCAT_Virtuos_Testprojekt_VirtuosIOWizard@1";
    
    	//Creating the Socket Object
    	socket = new QTcpSocket(this);
    	//Setting the IP Adress to the Target System. Will  later be set through User Input
    	QString  HostAdress = "192.168.10.10"; 
    	printf(QString("Connection to Host under " + HostAdress + " started\n").toStdString().c_str());
    	//Connecting to the Hose
    	socket->connectToHost(HostAdress, 8016);
    	if (!socket->waitForConnected(5000)) //Checking if the Connection is established
    	{
    		printf("Connection to Host failed\n");
    
    	}
    	else
    
    	{
    		printf(QString("Connected to " + HostAdress + " successfully\n").toStdString().c_str());
    		printf("checking if the configuration exists\n");
    		QFile TCFile(ZFsolutionFolder + ZFsolutionName + ".sln"); //Opening the Local File that will be sent
    		if (!TCFile.exists())
    		{
    			printf(QString(ZFsolutionName + " does not exist\n").toStdString().c_str());
    		}
    		else
    
    		{
    			printf("file exists. Opening...\n");
    			TCFile.open(QIODevice::ReadOnly);
    		}
    		QByteArray q = TCFile.readAll();
    		socket->write(q);
    	}
    }
    

    If my Code is right, it connects to the Host under the given Ip Address and writes the local File to the Socket. The next Step would be to make the Code that reads the File from the Socket and saves it to a given Path on the Target Computer. That's where i'm stuck at the moment.

    Can anyone give me any hints or recommend any examples on how to accomplish this?

    Every tip is welcome !! Thanks !!



  • @JohnSRV
    For the server side, you might like to look through the https://doc.qt.io/qt-5/qtnetwork-fortuneserver-example.html example, though your situation might be a bit simpler.

    You will kind of do the reverse from your client here: read the bytes arriving on the socket, write them to a file. The only "wriggle" is you won't be able to get with a single socket->readAll() where you have s single socket->write() in your client. You will need to use signals & slots, to save data as it arrives.



  • @JonB hey thanks for your answer.
    So I implemented the server side. Here's the header File to the Server:

    #ifndef  SERVER_H
    #define  SERVER_H
    
    
    #include <QObject>
    #include <QTcpSocket>
    #include <QAbstractSocket>
    #include <QDataStream>
    #include <QTcpServer>
    #include <QHostAddress>
    #include <QDialog>
    #include <QLabel>
    #include "SocketThread.h"
    
    
    class Server : public QTcpServer
    {
    	Q_OBJECT
    
    public:
    	explicit Server(QHostAddress  host = QHostAddress::Any,
    					quint16 port = 8016,
    					QObject *parent = 0);
    
    	~Server();
    
    
    	void incomingConnection(qintptr handle) Q_DECL_OVERRIDE;
    
    signals:
    
    public  slots:
    	void start();
    
    
    
    
    private:
    	
    	QHostAddress m_host; 
    	quint16		 m_port;
    	
    };
    #endif
    

    and the Server.cpp

    #include "Server.h"
    #include <QFile>
    #include "moc_Server.cpp"
    #include <QMessageBox>
    #include <QList>
    #include <QNetworkInterface>
    #include "SocketThread.h"
    
    
    Server::Server(QHostAddress host, quint16 port, QObject *parent) :
    	QTcpServer(parent),
    	m_host(host),
    	m_port(port)
    	{
    	}
    Server::~Server()
    {
    	printf("~Server");
    }
    
    void Server::start()
    {
    	QHostAddress pHost;
    	pHost.setAddress("192.168.10.10"); //Setting the Address of the Server to the Address of the target system
    	QString printAddress;
    	printAddress = pHost.toString();
    
    	if (this->listen(QHostAddress::Any, 8016))
    
    	{
    		printf(QString("Server started at " + printAddress+ "and Listening \n").toStdString().c_str());
    	}
    	else
    	{
    		printf("Server could not be started \n");
             }
    }
    
    void Server::incomingConnection(qintptr handle)
    {
    	printf("incoming Connection");
    	SocketThread *thread = new SocketThread(handle);
    	connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
    
    thread->start(); //this jumps directly to the run function in the socket thread. 
    

    }

    I implemented the Thread as following:

    #include "SocketThread.h"
    #include "moc_SocketThread.cpp"
    #include <Qt>
    #include <QFile>
    #include "Client.h"
    
    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(); //this keeps the thread running. Otherwise it will end automatically
    }
    
    void SocketThread::onReadyRead()
    {
    	
    
    	QString fileName;  //String for the file name
    	fileName = "TwinCAT_Virtuos_Testprojekt_VirtuosIOWizard@1";
    
    	QByteArray line = m_socket->readAll(); //reading Data from the Socket and returning it as a byte array
    	QString FilePath = "C:\\test"; // hier the Path on the receiving End
    	QFile target(FilePath + "/" + fileName);
    
    	if (!target.open(QIODevice::WriteOnly)) { //opening the File to write the incoming Data to it 
    
    		printf("can't open File for writing");
    
    	}
    
    	target.write(line); //Writing the byte Array line to the target file 
    	target.close();
    
    	emit onFinishRecieved();
    	m_socket->disconnectFromHost();
    
    }
    
    void SocketThread::onDisconnected()
    {
    	m_socket->close();
    
    	quit();
    }
    

    The Server starts successfully and is listening. The clients connects with Data to write. The Problem is that the function incomingConnection(qintptr handle) is not executed. What am I missing??

    Any hint is highly appreciated. Thanks !



  • @JohnSRV
    I don't know, but you could compare your threaded example to the accepted solution in https://stackoverflow.com/questions/31720030/qt-qtcpserverincomingconnectionqintptr-handle-not-firing.

    There is also https://www.bogotobogo.com/Qt/Qt5_QTcpServer_Multithreaded_Client_Server.php.

    You should also look at https://stackoverflow.com/questions/39085195/qtcpserverincomingconnectionqintptr-not-calling. It looks similar to yours. However, I note --- I think --- that the listen() is done in the main thread and a new thread is only spawned after a connection has been received.

    I know no more than the above.



  • @JonB I'm gonna give these examples a deep look. Thanks for posting the Links !


Log in to reply