- 1. Структура проекта
- 2. widget.h
- 3. widget.cpp
- 4. Итог
Для работы с сетью в Qt 5 используется модуль Network , а для передачи данных по сети можно активно использовать класс QNetworkAccessManager , если Вы не создаёте свой собственный протокол для передачи данных. Но для работы с FTP достаточно использования QNetworkAccessManager , с которым мы уже работали при реализации скачивания файла с сайта .
Напишем небольшую программу, которая будет загружать на сервер произвольный файл, который мы будем выбирать на нашем ПК с помощью диалога выбора файла. Также будет показан прогресс загрузки файла на FTP сервер.
Для этого в окне приложения будет присутствовать кнопка для открытия диалога выбора файла. QLineEdit, в котором будет отображаться путь к файлу. QLineEdit, в который мы будем вводить адрес, по которому будет производиться загрузка файла. Кнопка запуска загрузки, а также прогресс бар, который покажет прогресс загрузки файла на сервер.
Структура проекта
- UploadFile.pro - профайл проекта.
- main.cpp - файл функции main.
- widget.h - заголовочный файл окна приложения.
- widget.cpp - файл реализации окна приложения.
- widget.ui - файл формы окна приложения.
В профайл проекта необходимо добавить модуль network, чтобы работать с QNetworkAccessManger`ом.
- QT += network
Файл main.cpp создаётся по умолчанию и изменению не подвергается. В графическом дизайнере будет создана форма окна, которое было показано в начале статьи.
widget.h
- #ifndef WIDGET_H
- #define WIDGET_H
- #include <QWidget>
- #include <QNetworkAccessManager>
- #include <QNetworkReply>
- #include <QString>
- #include <QFile>
- namespace Ui {
- class Widget;
- }
- class Widget : public QWidget
- {
- Q_OBJECT
- public:
- explicit Widget(QWidget *parent = 0);
- ~Widget();
- private slots:
- void on_selectFileButton_clicked(); // Слот для вызова диалога выбора файла
- void on_uploadButton_clicked(); // Слот для запуска загрузки
- void uploadFinished(QNetworkReply *reply); // Слот окончания загрузки
- void uploadProgress(qint64 bytesSent, qint64 bytesTotal); // Слот прогресса загрузки
- private:
- Ui::Widget *ui;
- QNetworkAccessManager *m_manager;
- QString m_fileName;
- // Файл обязательно необходимо сохранять в куче
- // Если создавать объект файла в стеке, то программа будет крашиться.
- QFile *m_file;
- };
- #endif // WIDGET_H
widget.cpp
- #include "widget.h"
- #include "ui_widget.h"
- #include <QFileDialog>
- #include <QUrl>
- #include <QDebug>
- Widget::Widget(QWidget *parent) :
- QWidget(parent),
- ui(new Ui::Widget)
- {
- ui->setupUi(this);
- m_manager = new QNetworkAccessManager(this);
- connect(m_manager, &QNetworkAccessManager::finished, this, &Widget::uploadFinished);
- }
- Widget::~Widget()
- {
- delete ui;
- }
- void Widget::on_selectFileButton_clicked()
- {
- m_fileName = QFileDialog::getOpenFileName(this, "Get Any File");
- ui->fileNameLineEdit->setText(m_fileName);
- }
- void Widget::on_uploadButton_clicked()
- {
- // Создаём объект файла при запуске загрузки
- m_file = new QFile(m_fileName);
- // Далее требуется информация об имени файла
- // Путь загрузки на сервер должен выглядеть следующим образом
- // ftp://example.com/path/to/file/filename.txt
- // То есть указываем протокол -> ftp
- // Сервер -> example.com
- // Путь, где будет располагаться файла -> path/to/file/
- // И имя самого файла, который берём из QFileInfo -> filename.txt
- QFileInfo fileInfo(*m_file);
- QUrl url(ui->uploadUrlLineEdit->text() + fileInfo.fileName());
- url.setUserName("login"); // Устанавливаем login
- url.setPassword("password"); // Устанавливаем пароль
- url.setPort(21); // Порт протокола, по которому будем работать
- if (m_file->open(QIODevice::ReadOnly))
- {
- // Запускаем загрузку
- QNetworkReply *reply = m_manager->put(QNetworkRequest(url), m_file);
- // и коннектимся к сигналу прогресса загрузки
- connect(reply, &QNetworkReply::uploadProgress, this, &Widget::uploadProgress);
- }
- }
- void Widget::uploadFinished(QNetworkReply *reply)
- {
- // Если загрузка прошла без ошибок
- if (!reply->error())
- {
- // то закрываем файл
- m_file->close();
- m_file->deleteLater(); // Удаляем объект файла
- reply->deleteLater(); // Удаляем объект ответа
- }
- }
- void Widget::uploadProgress(qint64 bytesSent, qint64 bytesTotal)
- {
- // отображаем прогресс загрузки
- ui->progressBar->setValue(100 * bytesSent/bytesTotal);
- }
Итог
В результате получится загрузить выбранный файл на FTP сервер (хотя конечно в сети на форумах и есть сообщения о том, что не все FTP-сервера работают хорошо, но это уже нюансы).
Также отмечу, что в данной программе мало проверок и валидаций, поэтому вводите путь к серверу так, чтобы строка была закрыта слешем. Например:
ftp://example.com/path/to/file/