DPS_Manage/FileTransfer.h

211 lines
7.9 KiB
C
Raw Normal View History

2025-05-29 14:04:05 +08:00
#ifndef FILETRANSFER_H
#define FILETRANSFER_H
#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QFile>
#include <QDir>
#include <QFileInfo>
#include <QJsonDocument>
#include <QJsonObject>
#include <QHttpMultiPart>
class FileTransfer : public QObject {
Q_OBJECT
Q_PROPERTY(double downloadProgress READ downloadProgress NOTIFY downloadProgressChanged)
Q_PROPERTY(double uploadProgress READ uploadProgress NOTIFY uploadProgressChanged)
public:
static FileTransfer* instance() {
static FileTransfer _instance;
return &_instance;
}
Q_INVOKABLE void postDownload(const QString& url,
const QString& savePath,
const QVariantMap& postData,
const QString& additionalobj) {
if (m_currentDownload) {
emit downloadCompleted(false, u8"已有进行中的下载");
return;
}
// 获取文件所在的目录路径
QFileInfo fileInfo(savePath);
QString dirPath = fileInfo.absolutePath();
// 检查目录是否存在,如果不存在则创建
QDir dir;
if (!dir.exists(dirPath)) {
if (!dir.mkpath(dirPath)) {
emit downloadCompleted(false, u8"无法创建目录");
cleanup();
return;
}
}
// 创建目标文件
m_downloadFile = new QFile(savePath, this);
if (!m_downloadFile->open(QIODevice::WriteOnly)) {
emit downloadCompleted(false, u8"无法创建文件");
cleanup();
return;
}
QUrl u(url);
// 配置 HTTPS
QNetworkRequest request(u);
QSslConfiguration sslConfig = request.sslConfiguration();
sslConfig.setPeerVerifyMode(QSslSocket::VerifyNone); // 跳过证书验证
request.setSslConfiguration(sslConfig);
// 构建 POST 数据JSON 格式示例)
QJsonDocument jsonDoc(QJsonObject::fromVariantMap (postData));
QByteArray postBody = jsonDoc.toJson();
// 发送请求
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
m_currentDownload = manager.post(request, postBody);
// 连接信号
connect(m_currentDownload, &QNetworkReply::readyRead, [this](){
m_downloadFile->write(m_currentDownload->readAll());
});
connect(m_currentDownload, &QNetworkReply::downloadProgress,
[this,additionalobj](qint64 bytesReceived, qint64 bytesTotal){
m_downloadProgress = bytesTotal > 0
? bytesReceived / (double)bytesTotal
: 0;
emit downloadProgressChanged(m_downloadProgress,additionalobj);
});
connect(m_currentDownload, &QNetworkReply::finished, [this,additionalobj](){
if (m_downloadFile) {
m_downloadFile->flush();
m_downloadFile->close();
}
2025-09-15 09:46:04 +08:00
QVariant statusCodeVariant = m_currentDownload->attribute(QNetworkRequest::HttpStatusCodeAttribute);
if (statusCodeVariant.isValid()) {
int statusCode = statusCodeVariant.toInt();
qDebug() << "HTTP Status Code:" << statusCode;
}
2025-05-29 14:04:05 +08:00
bool success = !m_currentDownload->error();
QString message = success ? additionalobj : m_currentDownload->errorString();
if (success) {
// 验证文件完整性
QFileInfo fi(m_downloadFile->fileName());
qint64 expectedSize = m_currentDownload->header(
QNetworkRequest::ContentLengthHeader).toLongLong();
if (fi.size() != expectedSize && expectedSize > 0) {
success = false;
message = "文件不完整";
}
}
cleanup();
emit downloadCompleted(success, message.toUtf8());
});
}
Q_INVOKABLE void postUpload(const QString& url,
const QString& filePath,
const QString& remotePath,
const QString& additionalobj) {
if (m_currentDownload) { // 复用同一个网络管理器,保持单请求
emit uploadCompleted(false, u8"已有进行中的传输");
return;
}
// 准备要上传的文件
QFile *uploadFile = new QFile(filePath, this);
if (!uploadFile->open(QIODevice::ReadOnly)) {
emit uploadCompleted(false, u8"无法打开文件");
uploadFile->deleteLater();
return;
}
// 创建多部分数据
QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType, this);
// 添加文件部分
QHttpPart filePart;
filePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/octet-stream"));
filePart.setHeader(QNetworkRequest::ContentDispositionHeader,
QVariant(QString("form-data; name=\"file\"; filename=\"%1\"")
.arg(remotePath + QFileInfo(filePath).fileName())));
filePart.setBodyDevice(uploadFile);
uploadFile->setParent(multiPart); // 文件对象由multiPart管理生命周期
multiPart->append(filePart);
QUrl u(url);
QNetworkRequest request(u);
// 配置HTTPS
QSslConfiguration sslConfig = request.sslConfiguration();
sslConfig.setPeerVerifyMode(QSslSocket::VerifyNone);
request.setSslConfiguration(sslConfig);
// 发送请求
m_currentDownload = manager.post(request, multiPart);
multiPart->setParent(m_currentDownload); // 由reply管理multiPart生命周期
// 连接进度信号
connect(m_currentDownload, &QNetworkReply::uploadProgress,
[this, additionalobj](qint64 bytesSent, qint64 bytesTotal){
m_uploadProgress = bytesTotal > 0
? bytesSent / (double)bytesTotal
: 1;
emit uploadProgressChanged(m_uploadProgress, additionalobj); // 带附加参数
});
// 处理完成信号
connect(m_currentDownload, &QNetworkReply::finished, [this, additionalobj](){
bool success = (m_currentDownload->error() == QNetworkReply::NoError);
QString message = success ? u8"上传成功" : m_currentDownload->errorString();
cleanup();
emit uploadCompleted(success, additionalobj);
});
}
double downloadProgress() const { return m_downloadProgress; }
double uploadProgress() const { return m_uploadProgress; }
signals:
// 下载相关信号
void downloadProgressChanged(double progress,const QString& additional);
void downloadCompleted(bool success, const QString& message);
// 上传相关信号(原有)
void uploadProgressChanged(double progress ,const QString& additional);
void uploadCompleted(bool success, const QString& message);
private:
explicit FileTransfer(QObject* parent = nullptr)
: QObject(parent), m_downloadProgress(0), m_uploadProgress(0),
m_currentDownload(nullptr), m_downloadFile(nullptr) {}
QNetworkAccessManager manager;
double m_downloadProgress;
double m_uploadProgress;
QNetworkReply* m_currentDownload;
QFile* m_downloadFile;
void cleanup() {
if (m_downloadFile) {
m_downloadFile->deleteLater();
m_downloadFile = nullptr;
}
if (m_currentDownload) {
m_currentDownload->deleteLater();
m_currentDownload = nullptr;
}
m_downloadProgress = 0;
}
};
#endif // FILETRANSFER_H