文章目录
- 0 背景
- 1 搭建文件服务器
- 2 代码实现文件上传和下载
- 2.1 在pro文件中添加网络支持
- 2.2 创建网络管理类
- 2.3 文件上传
- 2.4 文件下载
- 3 扩展(其他方法实现文件上传和下载)
- 3.1 python
- 3.2 npm
- 3.3 ftp服务器
- 4 完整的代码
0 背景
因为需要使程序具备在远程软件在服务器的上传和下载文件的功能,所以研究了一下怎么实现。
1 搭建文件服务器
常用的文件服务器有apache、npm、ftp,这里选择的apache2,因为搭建和使用都比较方便。
1,安装
sudo apt update
sudo apt install apache2
2,创建身份验证用户::
# 新增用户
htpasswd -c /etc/apache2/webdav.password 【webdav用户名】# 更改密码
htpasswd -b /etc/apache2/webdav.password 【这里换成你要登录webdav的名字】 # 删除用户
htpasswd -D htpasswd.user Jack
3,编写配置文件
vim /etc/apache2/sites-available/000-default.conf
修改为如下内容:
<VirtualHost *:9022># The ServerName directive sets the request scheme, hostname and port that# the server uses to identify itself. This is used when creating# redirection URLs. In the context of virtual hosts, the ServerName# specifies what hostname must appear in the request's Host: header to# match this virtual host. For the default virtual host (this file) this# value is not decisive as it is used as a last resort host regardless.# However, you must set it for any further virtual host explicitly.#ServerName www.example.comServerAdmin webmaster@localhostDocumentRoot /var/www/html<Directory "/var/www/html">Dav onOptions Indexes FollowSymLinks MultiViewsAllowOverride AllRequire all grantedallow from all
</Directory>DavLockDB "/home/apache2/data/DavLock"
# 配置一个虚拟目录
Alias /webdav /home/apache2/data<Directory /home/apache2/data>
#开启Dav支持Dav On
# 禁止浏览器显示目录,将-Indexes前的减号去掉为允许显示(当index.html不存在时)Options Indexes
# 认证方式,虽然这种方式不安全但可以快速架设成功我们需要的服务 AuthType Basic# 这里的名字随意写 AuthName "WebDAV"# 非常关键的用户管理文件 AuthUserFile /etc/apache2/webdav.passwordAuthBasicProvider file# 允许userfile.pass里的所有用户访问 Require valid-userAllowOverride All
</Directory></VirtualHost>
授予文件访问权限:
sudo chmod 775 /var/www
4,启动并使其自动运行:
sudo systemctl start apache2
sudo systemctl status apache2
sudo systemctl enable apache2
5,其他指令
# 重启 Apache(完全停止并重新启动 Apache 服务。这适用于那些进行了重大更改并需要完全重启服务的情况):
sudo systemctl restart apache2# systemctl reload 只是重新加载 Apache 的配置文件,而不会中断服务的运行:
sudo systemctl reload apache2
2 代码实现文件上传和下载
2.1 在pro文件中添加网络支持
QT += network
2.2 创建网络管理类
# .h文件中添加:private://发送网络请求和接受应答QNetworkAccessManager* m_networkAccessManager;# .cpp文件中添加:m_networkAccessManager = new QNetworkAccessManager();
2.3 文件上传
1,功能函数;
//上传文件
void MainInterface::uploadFileFromHttpServerApacheWebdav(QString sourceFilePath, QString purposeFilePath)
{// QFile file(sourceFilePath);m_readFile.setFileName(sourceFilePath);if (m_readFile.open(QIODevice::ReadOnly)){QFileInfo fileInfo(sourceFilePath);QString fileName = fileInfo.fileName();//如果目的文件名,使用原文件名if(purposeFilePath == ""){purposeFilePath = fileName;}QString urlText = QString("http://192.168.0.211:9022/webdav/") + purposeFilePath;qDebug()<<urlText;QUrl url(urlText);// 设置用户名和密码凭据QString username = "uploaduser2";QString password = "test";url.setUserName(username);url.setPassword(password);m_httpRequest.setUrl(url);m_networkAccessManager->put(m_httpRequest, &m_readFile);}else{qDebug()<<"打开文件失败";}}
2,方法调用;
//文件上传QString sourceFilePath = QString("E:/s1.xlsx");QString purposeFilePath = "";uploadFileFromHttpServerApacheWebdav(sourceFilePath, purposeFilePath);
2.4 文件下载
这里下载使用的是post方法,而没有使用get。
1,功能函数;
//从服务器上下载文件
void MainInterface::downloadFileFromHttpServerApacheWebdav(QString sourceFilePath, QString purposeFilePath){QString urlText = QString("http://192.168.0.211:9022/webdav/") + sourceFilePath;QUrl url(urlText);// 设置用户名和密码凭据QString username = "uploaduser2";QString password = "test";url.setUserName(username);url.setPassword(password);m_httpRequest.setUrl(url);QString saveFilePath = QCoreApplication::applicationDirPath() + QString("/") ;//末尾无斜杠m_purposeSaveFilePath = saveFilePath + purposeFilePath;m_isReceiveFile = true;m_networkAccessManager->get(m_httpRequest);}//处理所有post请求connect(m_networkAccessManager, &QNetworkAccessManager::finished,this, [&](QNetworkReply *reply){if (reply->error()) {qDebug() << "Download error:" << reply->errorString();} else {//接收并下载文件if(m_isReceiveFile == true){m_isReceiveFile = false;// 处理获取到的文件内容QByteArray fileData = reply->readAll();qDebug() << "写入下载的数据:"<<m_purposeSaveFilePath;QFile file(m_purposeSaveFilePath);//QFile file(purposeFilePath);if (file.open(QIODevice::WriteOnly)) {file.write(fileData);file.close();}}else{QVariant data = reply->readAll();qDebug()<<data.toString();}}reply->deleteLater();});
2,方法调用;
QString sourceFilePath = "s5.xlsx";QString purposeFilePath = "data/s5.xlsx";downloadFileFromHttpServerApacheWebdav(sourceFilePath, purposeFilePath);
3 扩展(其他方法实现文件上传和下载)
3.1 python
下载和安装python3,然后使用如下指令开启服务器
python -m http.server -b 127.0.0.1
3.2 npm
1,安装
执行代码:
npm install http-server -g
-g 参数代表全局安装一定不要省略,全局安装后,全局都可以使用
2,在需要共享的文件夹下,运行
http-server
3.3 ftp服务器
1,安装(https://www.myfreax.com/how-to-setup-ftp-server-with-vsftpd-on-debian-11/)
sudo apt update
sudo apt install vsftpd
sudo systemctl status vsftpd
2,新建ftp登录账户
# 创建一个帐户
sudo adduser ftpuser# 为了让用户能够访问FTP服务器,你需要将其添加到FTP用户组中。输入以下命令:sudo usermod -a -G ftp ftpuser
3,修改配置文件
修改/etc/shells
sudo vim /etc/shells#写入以下这行,否则ftpuser无法登录
/usr/sbin/nologin
修改内容:
# 启用上传
write_enable=YES#限制ftp用户只能待在自己的家目录,不能跳到其他目录
chroot_local_user=YES
allow_writeable_chroot=YES #不加入这条会导致ftp用户对家目录没有写入权限chroot_local_user=YES #限制ftp用户只能待在自己的家目录,不能跳到其他目录
userlist_enable=YES #使用userlist限制可以登录ftp的账户
userlist_deny=NO #这里是NO则userlist是白名单,YES就是黑名单
4,重启vsftpd服务
sudo systemctl restart vsftpd
systemctl start vsftpd.service
sudo systemctl status vsftpd
4 完整的代码
MainInterface.h
#ifndef MAIN_INTERFACE_H
#define MAIN_INTERFACE_H#include <QMainWindow>#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QFile>QT_BEGIN_NAMESPACE
namespace Ui {
class MainInterface;
}
QT_END_NAMESPACEclass MainInterface : public QMainWindow
{Q_OBJECTpublic:MainInterface(QWidget *parent = nullptr);~MainInterface();private:Ui::MainInterface *ui;private://发送网络请求和接受应答QNetworkAccessManager* m_networkAccessManager;//是否是接收文件bool m_isReceiveFile = false;//目的存储路径QString m_purposeSaveFilePath;//请求QNetworkRequest m_httpRequest;//文件下载QFile m_readFile;/*** @brief downloadFileFromHttpServerApacheWebdav:从apache2服务器上下载文件(get)* @param sourceFilePath:源文件路径(最前面不带/,)* @param purposeFilePath:目的文件路径(最前面不带/,最前面包含了运行文件的路径)*/void downloadFileFromHttpServerApacheWebdav(QString sourceFilePath, QString purposeFilePath);/*** @brief 上传文件到服务器上(put)* @param sourceFilePath* @param purposeFilePath*/void uploadFileFromHttpServerApacheWebdav(QString sourceFilePath, QString purposeFilePath);
};
#endif // MAIN_INTERFACE_H
MainInterface.cpp
#include "main_interface.h"
#include "ui_main_interface.h"#include <QDebug>#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QUrl>
#include <QObject>
#include <QFile>
#include <QFileInfo>MainInterface::MainInterface(QWidget *parent): QMainWindow(parent), ui(new Ui::MainInterface)
{ui->setupUi(this);// qDebug() << QSslSocket::supportsSsl()//是否支持,不支持就说明没有openSSL// << QSslSocket::sslLibraryBuildVersionString()//运行时需要的版本// << QSslSocket::sslLibraryVersionString();//可用的版本m_networkAccessManager = new QNetworkAccessManager();//处理所有post请求connect(m_networkAccessManager, &QNetworkAccessManager::finished,this, [&](QNetworkReply *reply){if (reply->error()) {qDebug() << "Download error:" << reply->errorString();} else {//接收并下载文件if(m_isReceiveFile == true){m_isReceiveFile = false;// 处理获取到的文件内容QByteArray fileData = reply->readAll();qDebug() << "写入下载的数据:"<<m_purposeSaveFilePath;QFile file(m_purposeSaveFilePath);//QFile file(purposeFilePath);if (file.open(QIODevice::WriteOnly)) {file.write(fileData);file.close();}}else{QVariant data = reply->readAll();qDebug()<<data.toString();}}reply->deleteLater();});//文件下载// QString sourceFilePath = "s5_ExamineExamOne_1721294100.xlsx";// QString purposeFilePath = "data/s5_ExamineExamOne_1721294100.xlsx";// downloadFileFromHttpServerApacheWebdav(sourceFilePath, purposeFilePath);//文件上传QString sourceFilePath = QString("E:/s1.xlsx");QString purposeFilePath = "";uploadFileFromHttpServerApacheWebdav(sourceFilePath, purposeFilePath);}MainInterface::~MainInterface()
{delete ui;
}//从服务器上下载文件
void MainInterface::downloadFileFromHttpServerApacheWebdav(QString sourceFilePath, QString purposeFilePath){QString urlText = QString("http://192.168.0.211:9022/webdav/") + sourceFilePath;QUrl url(urlText);// 设置用户名和密码凭据QString username = "uploaduser2";QString password = "test";url.setUserName(username);url.setPassword(password);m_httpRequest.setUrl(url);QString saveFilePath = QCoreApplication::applicationDirPath() + QString("/") ;//末尾无斜杠m_purposeSaveFilePath = saveFilePath + purposeFilePath;m_isReceiveFile = true;m_networkAccessManager->get(m_httpRequest);}//上传文件
void MainInterface::uploadFileFromHttpServerApacheWebdav(QString sourceFilePath, QString purposeFilePath)
{// QFile file(sourceFilePath);m_readFile.setFileName(sourceFilePath);if (m_readFile.open(QIODevice::ReadOnly)){QFileInfo fileInfo(sourceFilePath);QString fileName = fileInfo.fileName();//如果目的文件名,使用原文件名if(purposeFilePath == ""){purposeFilePath = fileName;}QString urlText = QString("http://192.168.0.211:9022/webdav/") + purposeFilePath;qDebug()<<urlText;QUrl url(urlText);// 设置用户名和密码凭据QString username = "uploaduser2";QString password = "test";url.setUserName(username);url.setPassword(password);m_httpRequest.setUrl(url);m_networkAccessManager->put(m_httpRequest, &m_readFile);}else{qDebug()<<"打开文件失败";}}