Evgenii Legotckoi
Evgenii Legotckoi6 июня 2017 г. 12: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`ом.

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/

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

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

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

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
m
  • moreSpb
  • 18 марта 2024 г. 15:32

C++ - Тест 003. Условия и циклы

  • Результат:85баллов,
  • Очки рейтинга6
в

C++ - Тест 003. Условия и циклы

  • Результат:50баллов,
  • Очки рейтинга-4
l

C++ - Тест 005. Структуры и Классы

  • Результат:91баллов,
  • Очки рейтинга8
Последние комментарии
k
kmssr8 февраля 2024 г. 18:43
Qt Linux - Урок 001. Автозапуск Qt приложения под Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
АК
Анатолий Кононенко5 февраля 2024 г. 1:50
Qt WinAPI - Урок 007. Работаем с ICMP Ping в Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVA25 декабря 2023 г. 10:30
Boost - статическая линковка в CMake проекте под Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
J
JonnyJo25 декабря 2023 г. 8:38
Boost - статическая линковка в CMake проекте под Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
G
Gvozdik18 декабря 2023 г. 21:01
Qt/C++ - Урок 056. Подключение библиотеки Boost в Qt для компиляторов MinGW и MSVC Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
Сейчас обсуждают на форуме
P
Pisych27 февраля 2023 г. 4:04
Как получить в массив значения из связанной модели? Спасибо, разобрался:))
AC
Alexandru Codreanu19 января 2024 г. 11:57
QML Обнулить значения SpinBox Доброго времени суток, не могу разобраться с обнулением значение SpinBox находящего в делегате. import QtQuickimport QtQuick.ControlsWindow { width: 640 height: 480 visible: tr…
BlinCT
BlinCT27 декабря 2023 г. 8:57
Растягивать Image на парент по высоте Ну и само собою дял включения scrollbar надо чтобы был Flickable. Так что выходит как то так Flickable{ id: root anchors.fill: parent clip: true property url linkFile p…
Дмитрий
Дмитрий10 января 2024 г. 4:18
Qt Creator загружает всю оперативную память Проблема решена. Удалось разобраться с помощью утилиты strace. Запустил ее: strace ./qtcreator Начал выводиться весь лог работы креатора. В один момент он начал считывать фай…
Evgenii Legotckoi
Evgenii Legotckoi12 декабря 2023 г. 6:48
Побуквенное сравнение двух строк Добрый день. Там случайно не высылается этот сигнал textChanged ещё и при форматировани текста? Если решиать в лоб, то можно просто отключать сигнал/слотовое соединение внутри слота и …

Следите за нами в социальных сетях