#include "client.h"
#include <QDebug>
#include <QNetworkAccessManager>
#include <QFileInfo>
QString ConvertSize(qint64 size){
QString output("0 Bytes");
if(size<1024){
output=QString::number(size)+" Bytes";
return output;
}else if(size>1024 && size <1048576){
double newNumber=size/1024.0;
output=QString::number(newNumber)+" KBs";
return output;
}else if(size >1048576){
double newNumber=size/1048576.0;
output=QString::number(newNumber)+" MBs";
return output;
}else if(size >1073741824){
double newNumber=size/1073741824.0;
output=QString::number(newNumber)+" GBs";
return output;
}else{
return output;
}
}
Client::Client(QObject *parent)
: QObject{parent}
{
qInfo()<<this<<"constructed on: "<<QThread::currentThread();
connect(&ftp,&QFtp::commandStarted,this,&Client::commandStarted);
connect(&ftp,&QFtp::commandFinished,this,&Client::commandFinished);
connect(&ftp,&QFtp::dataTransferProgress,this,&Client::dataProgress);
connect(&ftp,&QFtp::done,this,&Client::done);
connect(&ftp,&QFtp::listInfo,this,&Client::listInfo);
connect(&ftp,&QFtp::stateChanged,this,&Client::stateChanged);
connect(&ftp,&QFtp::rawCommandReply,this,&Client::rawCommandReply);
}
Client::~Client()
{
qInfo()<<this<<"deConstructed on: "<<QThread::currentThread();
}
void Client::connectToHost(QString ip, quint16 port)
{
qInfo()<<"connecting to "<<ip<<":"<<port;
ftp.connectToHost(ip,port);
qInfo()<<"loging in";
ftp.login("testuser","123456");
}
void Client::commandStarted(int id)
{
//qInfo()<<"command start:"<<id;
quint8 command=ftp.currentCommand();
switch (command){
case 0:qInfo()<<"command start: "<<"None";break;
case 1:qInfo()<<"command start: "<<"SetTransferMode";break;
case 2:qInfo()<<"command start: "<<"SetProxy";break;
case 3:qInfo()<<"command start: "<<"ConnectToHost";break;
case 4:qInfo()<<"command start: "<<"Login";break;
case 5:qInfo()<<"command start: "<<"Close";break;
case 6:qInfo()<<"command start: "<<"List";break;
case 7:qInfo()<<"command start: "<<"Cd";break;
case 8:qInfo()<<"command start: "<<"Get";break;
case 9:qInfo()<<"command start: "<<"Put";break;
case 10:qInfo()<<"command start: "<<"Remove";break;
case 11:qInfo()<<"command start: "<<"Mkdir";break;
case 12:qInfo()<<"command start: "<<"Rmdir";break;
case 13:qInfo()<<"command start: "<<"Rename";break;
case 14:qInfo()<<"command start: "<<"RawCommand";break;
}
}
void Client::commandFinished(int id)
{
qInfo()<<"command finished: "<<id;
if(ftp.error()){
qInfo()<<ftp.errorString();
}else{
qInfo()<<"no error";
}
if(ftp.currentCommand()==9){
myfile->flush();
myfile->close();
myfile->deleteLater();
myfile=NULL;
qInfo()<<"put command ended.closing open file.";
}
}
void Client::rawCommandReply(int code, QString detail)
{
qInfo()<<"reply code: "<<code<<"detail: "<<detail;
if (code==226){
qInfo()<<"transmission ended";
}
if (code==150){
qInfo()<<"serverReady";
dataChanel();
}
if(code==227){
QString ip1=detail.split("(")[1];
QString ip2=ip1.split(")")[0];
qInfo()<<ip2;
QStringList data=ip2.split(",");
QStringList ip;
QStringList ports;
for (int i=0;i<data.size();i++){
if(i<4){
ip.append(data[i]);
}else {
ports.append(data[i]);
}
}
qInfo()<<"ip:"<<ip.join(".");
IpPorts.append(ip.join("."));
qInfo()<<"port:"<<ports.join("-");
for(int i=0;i<ports.size();i++){
IpPorts.append(ports[i]);
}
}
}
void Client::dataProgress(quint64 now, quint64 all)
{
qInfo()<<"now:\t"<<ConvertSize(now)<<"\t from:\t"<<ConvertSize(all);
}
void Client::done(bool error)
{
if (error){
qInfo()<<"error occured when done:"<<ftp.errorString();
}
//ftp.close();
qInfo()<<"ftp connection closed";
}
void Client::listInfo(const QUrlInfo &i)
{
qInfo()<<"dir found:"<<i.name();
}
void Client::stateChanged(int state)
{
switch(state){
case 0:qInfo()<<"state changed: "<<"Unconnected";break;
case 1:qInfo()<<"state changed: "<<"HostLookup";break;
case 2:qInfo()<<"state changed: "<<"Connecting";break;
case 3:qInfo()<<"state changed: "<<"Connected";break;
case 4:qInfo()<<"state changed: "<<"LoggedIn";break;
case 5:qInfo()<<"state changed: "<<"Closing";break;
}
}
void Client::abort()
{
ftp.abort();
qInfo()<<"ftp connection aborted";
}
void Client::ended()
{
qInfo()<<"ftp connection ended";
}
void Client::upload(QString &location)
{
myfile=new QFile(location);
if(myfile->open(QIODevice::ReadOnly)){
ftp.rawCommand("PASV");
ftp.rawCommand("TYPE I");
QFileInfo fileinfo(myfile->fileName());
qInfo()<<"size: "<<fileinfo.size();
qInfo()<<"name: "<<fileinfo.fileName();
qInfo()<<"uploading : "<<location;
//qInfo()<<"file name is:"<<myfile->fileName();
//ftp.put(myfile,fileinfo.fileName());
QString text="STOR "+fileinfo.fileName();
qInfo()<<text;
ftp.rawCommand(text);
//client.rawCommand("PASV");
//client.rawCommand("TYPE I");
//client.rawCommand("STAT");
//client.rawCommand("STOR test.txt");
}
}
void Client::list(QString &dir)
{
qInfo()<<"listing dir:"<<dir;
ftp.list(dir);
}
void Client::dataChanel()
{
for(int i=0;i<IpPorts.size();i++){
qInfo()<<IpPorts[i];
}
QTcpSocket* socket=new QTcpSocket(this);
socket->connectToHost(IpPorts[0],IpPorts[1].toInt());
QByteArray data;
data=myfile->readAll();
socket->waitForConnected();
socket->write(data);
}
i need to upload files to a server and to make it resumeable i need to user raw commands and REST.
Im using QFtp raw command STOR and when it returns code 227 i parse the data and get the ip and open port then when i recieve code 150 i open a tcp port as a data socket to send the data but after a few seconds it returns the error "Data channel timed out.\r\n Win32 error: The network connection was aborted by the local system." what am i doing wrong here?how am i supposed to use this command?
so i was reading about it and somewhere said that using PASV isnt smart and instead use EPSV to open a port.i changed my code like this and parsed the new port and changed user permissions of local ftp server to all users and it worked!