Evgenii Legotckoi
6 июня 2017 г. 22:48

Qt/C++ - Урок 066. Загрузка файлов на FTP сервер

Для работы с сетью в Qt 5 используется модуль Network , а для передачи данных по сети можно активно использовать класс QNetworkAccessManager , если Вы не создаёте свой собственный протокол для передачи данных. Но для работы с FTP достаточно использования QNetworkAccessManager , с которым мы уже работали при реализации скачивания файла с сайта .

Напишем небольшую программу, которая будет загружать на сервер произвольный файл, который мы будем выбирать на нашем ПК с помощью диалога выбора файла. Также будет показан прогресс загрузки файла на FTP сервер.

Для этого в окне приложения будет присутствовать кнопка для открытия диалога выбора файла. QLineEdit, в котором будет отображаться путь к файлу. QLineEdit, в который мы будем вводить адрес, по которому будет производиться загрузка файла. Кнопка запуска загрузки, а также прогресс бар, который покажет прогресс загрузки файла на сервер.


Структура проекта

  • UploadFile.pro - профайл проекта.
  • main.cpp - файл функции main.
  • widget.h - заголовочный файл окна приложения.
  • widget.cpp - файл реализации окна приложения.
  • widget.ui - файл формы окна приложения.

В профайл проекта необходимо добавить модуль network, чтобы работать с QNetworkAccessManger`ом.

  1. QT += network

Файл main.cpp создаётся по умолчанию и изменению не подвергается. В графическом дизайнере будет создана форма окна, которое было показано в начале статьи.

widget.h

  1. #ifndef WIDGET_H
  2. #define WIDGET_H
  3.  
  4. #include <QWidget>
  5. #include <QNetworkAccessManager>
  6. #include <QNetworkReply>
  7. #include <QString>
  8. #include <QFile>
  9.  
  10. namespace Ui {
  11. class Widget;
  12. }
  13.  
  14. class Widget : public QWidget
  15. {
  16. Q_OBJECT
  17.  
  18. public:
  19. explicit Widget(QWidget *parent = 0);
  20. ~Widget();
  21.  
  22. private slots:
  23. void on_selectFileButton_clicked(); // Слот для вызова диалога выбора файла
  24. void on_uploadButton_clicked(); // Слот для запуска загрузки
  25. void uploadFinished(QNetworkReply *reply); // Слот окончания загрузки
  26. void uploadProgress(qint64 bytesSent, qint64 bytesTotal); // Слот прогресса загрузки
  27.  
  28. private:
  29. Ui::Widget *ui;
  30. QNetworkAccessManager *m_manager;
  31. QString m_fileName;
  32.   // Файл обязательно необходимо сохранять в куче
  33.   // Если создавать объект файла в стеке, то программа будет крашиться.
  34. QFile *m_file;
  35. };
  36.  
  37. #endif // WIDGET_H

widget.cpp

  1. #include "widget.h"
  2. #include "ui_widget.h"
  3.  
  4. #include <QFileDialog>
  5. #include <QUrl>
  6. #include <QDebug>
  7.  
  8. Widget::Widget(QWidget *parent) :
  9. QWidget(parent),
  10. ui(new Ui::Widget)
  11. {
  12. ui->setupUi(this);
  13. m_manager = new QNetworkAccessManager(this);
  14. connect(m_manager, &QNetworkAccessManager::finished, this, &Widget::uploadFinished);
  15. }
  16.  
  17. Widget::~Widget()
  18. {
  19. delete ui;
  20. }
  21.  
  22. void Widget::on_selectFileButton_clicked()
  23. {
  24. m_fileName = QFileDialog::getOpenFileName(this, "Get Any File");
  25. ui->fileNameLineEdit->setText(m_fileName);
  26. }
  27.  
  28. void Widget::on_uploadButton_clicked()
  29. {
  30.   // Создаём объект файла при запуске загрузки
  31. m_file = new QFile(m_fileName);
  32.  
  33.   // Далее требуется информация об имени файла
  34.   // Путь загрузки на сервер должен выглядеть следующим образом
  35. // ftp://example.com/path/to/file/filename.txt
  36.   // То есть указываем протокол -> ftp
  37.   // Сервер -> example.com
  38.   // Путь, где будет располагаться файла -> path/to/file/
  39.   // И имя самого файла, который берём из QFileInfo -> filename.txt
  40. QFileInfo fileInfo(*m_file);
  41. QUrl url(ui->uploadUrlLineEdit->text() + fileInfo.fileName());
  42. url.setUserName("login"); // Устанавливаем login
  43. url.setPassword("password"); // Устанавливаем пароль
  44. url.setPort(21); // Порт протокола, по которому будем работать
  45.  
  46. if (m_file->open(QIODevice::ReadOnly))
  47. {
  48.   // Запускаем загрузку
  49. QNetworkReply *reply = m_manager->put(QNetworkRequest(url), m_file);
  50.   // и коннектимся к сигналу прогресса загрузки
  51. connect(reply, &QNetworkReply::uploadProgress, this, &Widget::uploadProgress);
  52. }
  53.  
  54. }
  55.  
  56. void Widget::uploadFinished(QNetworkReply *reply)
  57. {
  58.   // Если загрузка прошла без ошибок
  59. if (!reply->error())
  60. {
  61.   // то закрываем файл
  62. m_file->close();
  63. m_file->deleteLater(); // Удаляем объект файла
  64. reply->deleteLater(); // Удаляем объект ответа
  65. }
  66. }
  67.  
  68. void Widget::uploadProgress(qint64 bytesSent, qint64 bytesTotal)
  69. {
  70.   // отображаем прогресс загрузки
  71. ui->progressBar->setValue(100 * bytesSent/bytesTotal);
  72. }

Итог

В результате получится загрузить выбранный файл на FTP сервер (хотя конечно в сети на форумах и есть сообщения о том, что не все FTP-сервера работают хорошо, но это уже нюансы).

Также отмечу, что в данной программе мало проверок и валидаций, поэтому вводите путь к серверу так, чтобы строка была закрыта слешем. Например:

ftp://example.com/path/to/file/

Скачать проект

Вам это нравится? Поделитесь в социальных сетях!

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь