qt文件断点续传+nodejs搭建本地服务器

文章目录

    • nodejs服务器搭建
    • qt代码


用nodjs来搭建一个本地的服务器,用qt编写程序实现文件的上传和断点续传的功能

nodejs服务器搭建

先去安装一个nodejs,然后在文件夹中npm init -y初始化nodejs项目,npm install express multer安装所需要的包,在项目目录创建一个server.js文件,并添加下面的代码,最后用node server.js启动服务器,速成参考Node.js 教程 | 菜鸟教程 (runoob.com)

const express = require('express');
const path = require('path');
const fs = require('fs');
const app = express();
const port = 3000;// 提供静态文件服务
app.use(express.static('uploads'));// 处理文件上传的 PUT 请求
app.put('/upload', (req, res) => {// 获取文件名和扩展名const originalFileName = req.headers['x-filename'];const filePath = path.join(__dirname, 'uploads', originalFileName);const range = req.headers['range'];let start = 0;// 处理断点续传if (range) {const parts = range.replace(/bytes=/, "").split("-");start = parseInt(parts[0], 10);}// 创建文件写入流,从指定位置开始写入const uploadStream = fs.createWriteStream(filePath, { flags: 'a', start });// 处理文件上传数据req.on('data', chunk => {uploadStream.write(chunk);});// 处理上传完成req.on('end', () => {uploadStream.end();res.end(`File uploaded successfully as ${originalFileName}`);console.log(`File uploaded successfully as ${originalFileName}`);});// 处理上传中断req.on('aborted', () => {uploadStream.end();console.log('Upload aborted.');});// 处理上传错误req.on('error', err => {uploadStream.end();console.error('Upload error:', err);});
});// 启动服务器
app.listen(port, () => {console.log(`Server running at http://localhost:${port}`);
});

qt代码

  • fileuploader.h
#ifndef FILEUPLOADER_H
#define FILEUPLOADER_H#include <QDebug>
#include <QFile>
#include <QFileDialog>
#include <QLabel>
#include <QLineEdit>
#include <QMessageBox>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QObject>
#include <QProgressBar>
#include <QPushButton>
#include <QUrl>
#include <QVBoxLayout>class FileUploader : public QWidget
{Q_OBJECT
public:explicit FileUploader(QWidget *parent = nullptr);~FileUploader();signals:private slots:void selectFile();void startUpload();void pauseUpload();void handleUploadProgress(qint64 bytesSent, qint64 BytesTotal);void handleUploadFinished();public:QVBoxLayout *layout;   //定义垂直布局QHBoxLayout *hLayout1; //定义水平布局QHBoxLayout *hLayout2;QPushButton *selectButton;QPushButton *startButton;QPushButton *pauseButton;QLineEdit *filePathEdit;QProgressBar *progressBar;QWidget *centralWidget;private:QNetworkAccessManager *manager;QNetworkReply *reply;QFile *file;QString selectedFilePath;qint64 uploadBytes; //记录已上传字节数bool isPaused;      //是否已暂停
};#endif // FILEUPLOADER_H
  • fileuploader.cpp
#include "fileuploader.h"FileUploader::FileUploader(QWidget *parent): QWidget{parent}
{//窗口初始化layout = new QVBoxLayout();hLayout1 = new QHBoxLayout();hLayout2 = new QHBoxLayout();selectButton = new QPushButton("选择文件", this);startButton = new QPushButton("开始传输", this);pauseButton = new QPushButton("暂停传输", this);filePathEdit = new QLineEdit(this);progressBar = new QProgressBar(this);// progressBar->setRange(0, 100);// progressBar->setValue(0);hLayout1->addWidget(selectButton);hLayout1->addWidget(filePathEdit);hLayout1->addWidget(startButton);layout->addLayout(hLayout1);hLayout2->addWidget(progressBar);hLayout2->addWidget(pauseButton);layout->addLayout(hLayout2);centralWidget = new QWidget(this);centralWidget->setLayout(layout);//网络请求部分初始化manager = new QNetworkAccessManager(this);reply = nullptr;file = nullptr;uploadBytes = 0;isPaused = false;//信号槽注册connect(selectButton, &QPushButton::clicked, this, &FileUploader::selectFile);connect(startButton, &QPushButton::clicked, this, &FileUploader::startUpload);connect(pauseButton, &QPushButton::clicked, this, &FileUploader::pauseUpload);
}FileUploader::~FileUploader()
{reply->deleteLater();file->close();file->deleteLater();file = nullptr;
}void FileUploader::selectFile()
{selectedFilePath = QFileDialog::getOpenFileName(this, "选择一个文件");if (!selectedFilePath.isEmpty()) {filePathEdit->setText(selectedFilePath);}
}
//槽函数,处理开始上传按钮
void FileUploader::startUpload()
{if (selectedFilePath.isNull()) {qDebug() << "没有选择文件";}QUrl url("http://localhost:3000/upload");QNetworkRequest request(url);//设置头部字段,application/octet-stream是一个通用的二进制数据类型request.setHeader(QNetworkRequest::ContentTypeHeader, "application/octet-stream");//提取文件名并转为utf8编码的字节数组,作为http头部字段x-filename的值request.setRawHeader("x-filename", QFileInfo(selectedFilePath).fileName().toUtf8());file = new QFile(selectedFilePath);if (!file->open(QIODevice::ReadOnly)) {qDebug() << "文件打开错误";return;}qDebug() << "...........................";//如果文件尚未打开或已经关闭,重新打开if (file == nullptr || !file->isOpen()) {file = new QFile(selectedFilePath);if (!file->open(QIODevice::ReadOnly)) {qDebug() << "文件打开错误";return;}}if (uploadBytes > 0) {request.setRawHeader("Range", QByteArray("bytes=") + QByteArray::number(uploadBytes) + "-");file->seek(uploadBytes);}//发送put请求reply = manager->put(request, file);connect(reply, &QNetworkReply::uploadProgress, this, &FileUploader::handleUploadProgress);connect(reply, &QNetworkReply::finished, this, &FileUploader::handleUploadFinished);
}//槽函数,处理暂停按钮
void FileUploader::pauseUpload()
{if (reply && reply->isRunning()) {reply->abort();isPaused = true;pauseButton->setText("继续");qDebug() << uploadBytes;} else if (isPaused) {isPaused = false;startUpload(); //继续上传pauseButton->setText("暂停");}
}//槽函数,处理上传进度
void FileUploader::handleUploadProgress(qint64 bytesSent, qint64 BytesTotal)
{uploadBytes += bytesSent;progressBar->setMaximum(BytesTotal);progressBar->setValue(uploadBytes);
}//槽函数,传输完成
void FileUploader::handleUploadFinished()
{if (reply->error() == QNetworkReply::NoError) {qDebug() << "上传成功";QMessageBox::information(this, "提示", "上传成功");uploadBytes = 0;} else {qDebug() << "上传失败" << reply->errorString();}
}
  • mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);uploader = new FileUploader(this);//初始化窗口界面setCentralWidget(uploader->centralWidget);
}MainWindow::~MainWindow()
{delete ui;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/35697.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

嵌入式工程师从0开始,到底该学什么,怎么学

在开始前刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「嵌入式的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“666”之后私信回复“666”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01;嵌入式是个大筐&#xff0…

基于springboot实现宠物商城网站管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现宠物商城网站管理系统演示 摘要 传统信息的管理大部分依赖于管理人员的手工登记与管理&#xff0c;然而&#xff0c;随着近些年信息技术的迅猛发展&#xff0c;让许多比较老套的信息管理模式进行了更新迭代&#xff0c;商品信息因为其管理内容繁杂&#xff…

Windows Nginx更新版本

一、准备新版安装包 nginx: downloadhttps://nginx.org/en/download.html 二、升级Nginx 1、备份原Nginx 2、上传新版Nginx 上传并解压 3、更新版本 1&#xff09;原文件夹更新 1.关闭nginx 查看原版本号 nginx -v 命今关闭 nginx -s stop 确认进程里没有nginx&#…

【每日刷题】Day76

【每日刷题】Day76 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. 561. 数组拆分 - 力扣&#xff08;LeetCode&#xff09; 2. 删除有序链表中重复的元素-II_牛客题霸…

论文学习_基于导向式模糊测试的二进制程序漏洞验证方法

1. 引言 研究背景及现存问题:基于代码相似性比较的漏洞检测方法属于静态分析方法,不可避免地存在误报率高的问题,对静态检测方法得到的疑似漏洞代码进行人工分析存在工作量大, 效率低的问题。解决该问题的有效的方案之一是使用导向式模糊测试方法,生成能够执行到疑似漏洞…

【FFmpeg】avformat_open_input函数

【FFmpeg】avformat_open_input函数 1.avformat_open_input1.1 初始化输入格式&#xff08;init_input&#xff09;1.1.1 文件路径判断格式&#xff08;av_probe_input_format2&#xff09;1.1.1.1 格式探测&#xff08;read_probe&#xff09;1.1.1.2 扩展匹配检查&#xff08…

Pyecharts进阶篇

欢迎观看Pyecharts部分&#xff0c;上一节&#xff1a;Pyecharts入门-CSDN博客 本章节&#xff0c;我们会使用全国空气质量数据呈现中国地图&#xff0c;还会使用全球各个国家或地区GDP数据绘制全球地图。 全国空气质量分布图 数据准备 import pandas as pd import numpy a…

美国唱片公司以侵犯版权为由起诉人工智能音乐生成器

美国唱片公司以侵犯版权为由起诉人工智能音乐生成器 全球最大的几家唱片公司正联手将两家著名的人工智能音乐制作公司告上法庭&#xff0c;此举正值生成式人工智能继续渗透到音乐行业之际。 环球音乐集团、索尼音乐娱乐和华纳音乐集团等公司周一对Suno和音频制造商Uncharted …

树莓派4B_OpenCv学习笔记13:OpenCv颜色追踪_程序手动调试HSV色彩空间_检测圆

今日继续学习树莓派4B 4G&#xff1a;&#xff08;Raspberry Pi&#xff0c;简称RPi或RasPi&#xff09; 本人所用树莓派4B 装载的系统与版本如下: 版本可用命令 (lsb_release -a) 查询: Opencv 版本是4.5.1&#xff1a; OpenCv颜色追踪_程序手动调试HSV色彩空间_检测灰度图中的…

AI新热点:边云协同:大模型结合小模型(大小模型联合推理)

背景 AI模型规模不断剧增已是不争的事实。模型参数增长至百亿、千亿、万亿甚至十万亿&#xff0c;大模型在算力推动下演变为人工智能领域一场新的“军备竞赛”。 这种竞赛很大程度推动了人工智能的发展&#xff0c;但随之而来的能耗和端侧部署问题限制了大模型应用落地。2022…

4. ansible角色

ansible角色 一、ansible角色 role1、创建角色2、角色目录结构 二、部署zabbix-agent1、创建角色2、编写剧本3、执行角色中的操作 三、部署分布式zabbix1、zabbixproxy角色结构2、zabbixProxy task/main.yml3、zabbixAgentByProxy角色结构4、zabbixAgentByProxy tasks/main.yml…

非极大值抑制算法(Non-Maximum Suppression,NMS)

https://tcnull.github.io/nms/ https://blog.csdn.net/weicao1990/article/details/103857298 目标检测中检测出了许多的候选框&#xff0c;候选框之间是有重叠的&#xff0c;NMS作用重叠的候选框只保留一个 算法&#xff1a; 将所有候选框放入到集和B从B中选出分数S最大的b…

ubuntu安装QT

以QT5.15.14为例 下载地址&#xff1a;Index of /archive/qt 安装步骤&#xff1a; 解压qt-everywhere-src-5.15.14运行&#xff1a; cd qt-everywhere-src-5.15.14 mkdir build cd build ../configure -prefix /opt/qt5.15.14 -opensource -confirm-license make -j16 sudo…

keep-alive页面切回原滚动位置hook方法

keep-alive页面切回原滚动位置hook方法 原理hook使用 原理 如果使用了keep-alive组件&#xff0c;当前组件会额外增加两个生命周期。 activated&#xff1a;被 keep-alive 缓存的组件激活时调用 deactivated&#xff1a;被 keep-alive 缓存的组件失活时调用。 通过这两个声明周…

VBA技术资料MF168:移动工作表为单独工作簿

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套&#xff0c;分为初级、中级、高级三大部分&#xff0c;教程是对VBA的系统讲解&#…

eventbus和vuex

EventBus和Vuex EventBus 工作原理 创建一个vue实例&#xff0c;然后通过空的vue实例作为组件之间的桥梁&#xff0c;进行通信&#xff0c;利用到的设计模式有发布订阅模式 Vuex 工作原理 维护了一个state树&#xff0c;是独立的状态树&#xff0c;有明显的层级关系。不论…

云计算-期末复习题-框架设计/选择/填空/简答(2)

目录 框架设计 1.负载分布架构 2.动态可扩展架构 3.弹性资源容量架构 4.服务负载均衡架构 5.云爆发结构 6.弹性磁盘供给结构 7.负载均衡的虚拟服务器实例架构 填空题/简答题 单选题 多选题 云计算期末复习部分练习题&#xff0c;包括最后的部分框架设计大题(只是部分…

vue3工程引用vue2模块文件时所做的修改

vue3工程引用vue2模块文件&#xff0c;如果代码没改的话&#xff0c;编译运行时可能会报错&#xff1a; SyntaxError: The requested module /fs/D:/HBuilderX.3.8.7.20230703/HBuilderX/plugins/uniapp-cli-vite/node_modules/dcloudio/uni-h5-vue/dist/vue.runtime.esm.js do…

SchedulerLock LockProvider参数配置表,列,大小写等 分布式锁 定时任务锁 学习总结

一、SchedulerLock 使用场景 如果是分布式任务&#xff0c;即多个相同的应用执行定时任务&#xff0c;那么为了防止重复执行可以使用其他分布式锁做内部判断或其他形式的锁机制来防止重复执行。 SchedulerLock 提供了现成的封装好的分布式锁机制来防止定时任务被重复执行 gi…

jQuery动画与特效

显示与隐藏动画 语法&#xff1a; $(obj).show(duration,fn);显示 $(obj).hide(duration,fn);隐藏 $(obj).toggle(); 功能&#xff1a; 1. show()方法能动态地改变当前元素的高度、宽度和不透明度&#xff0c;最终显示当前元素&#xff1b; 2. hide()方法会动态地改变当前元素…