织梦做的网站后台怎么进,一套金蝶erp系统多少钱,和coser做网站,重庆微网站建设哪家好目录
上传文件功能的实现
uploadtask的设计
设置上传的槽函数
uploadFileAction接口 uploadFile接口
定时上传文件
进度条的设计 上传文件功能的实现 上传文件功能实现
1.双击 ”上传文件 “的 QListWidgetItem 或者 点击 “上传” 菜单项 都会弹出一个文件对话框 2.在文…目录
上传文件功能的实现
uploadtask的设计
设置上传的槽函数
uploadFileAction接口 uploadFile接口
定时上传文件
进度条的设计 上传文件功能的实现 上传文件功能实现
1.双击 ”上传文件 “的 QListWidgetItem 或者 点击 “上传” 菜单项 都会弹出一个文件对话框 2.在文件对话框选中对应的文件保存所有文件的路径在对话框中可以选中多个文件
3.将对应的文件存放到 uploadtask* m_uploadtask中uploadtask 是一个上传文件队列类型
4.定义m_uploadTimer定时器每0.5秒调用 uploadFileAction 进行上传文件。
5.uploadFileAction中先发送一个 md5 http请求给服务器
如果文件存在服务器则 秒传成功不需要将文件内容发送到服务器上如果文件不存在服务器则再发送一个upload的请求将文件的内容上传到服务器上。 6.妙传失败调用 uploadFile 接口将文件内容上传到服务器上。 uploadtask的设计
1.UploadFileInfo 是上传文件的信息的结构体 #define UPLOAD_NOT 0 //未上传
#define UPLOADING 1 //正在上传
#define UPLOAD_FINISHED 2 //上传完成
#define UPLOAD_FAILD 3 //上传失败
#define UPLOAF_FILE_EXISTE 4 //上传的文件已存在struct UploadFileInfo
{QString md5; //文件的md5值QString fileName; //文件名称QString filePath; //文件路径qint64 size; //文件大小FileDataProgress *fdp; //进度条int uploadStatus; //0.未上传1.正在上传2.上传完成
};
2.UploadTask 是 上传任务 列表类该 任务列表 存储的是即将上传的文件的信息 UploadFileInfo
//uploadtask.h文件//上传任务列表类, 单例模式
class UploadTask
{
public ://获取UploadTask唯一实例对象static UploadTask* getInstance();//添加文件到上传任务列表中int appendUploadTask(QString filePath);//判断任务列表是否为空bool isEmpty();//取出任务UploadFileInfo* takeTask();//删除任务void delUploadTask();//清空上传任务列表列表void clearList();
private:UploadTask();~UploadTask();//静态数据成员类中声明类外必须定义static UploadTask* m_instance;
private:QListUploadFileInfo* m_fileList;
};//uploadtask.cpp文件//添加文件到上传任务列表中
int uploadtask::appendUploadTask(QString filePath)
{QFileInfo* fileinfonew QFileInfo(filePath);if(fileinfo-size()30*1024*1024){//如果文件大于30mb则放弃该文件delete fileinfo;return -1;}//新建一个UploadFileInfo对象UploadFileInfo* uploadFileInfonew UploadFileInfo;uploadFileInfo-sizefileinfo-size();uploadFileInfo-fileNamefileinfo-fileName();uploadFileInfo-filePathfilePath;uploadFileInfo-md5Common::getInstant()-getFileMd5(filePath);uploadFileInfo-uploadStatusUPLOAD_NOT;//设置未上传状态filedataProgress* upProgressnew filedataProgress;upProgress-setName(uploadFileInfo-fileName);uploadFileInfo-fdpupProgress;//将进度条插入到上传列表中uploadlayout::getInstant()-getVLayout()-insertWidget(0,upProgress);m_filelist.append(uploadFileInfo);
}//判断任务列表是否为空
bool uploadtask::isEmpty()
{return m_filelist.empty();
}//取出任务
UploadFileInfo* uploadtask::takeTask()
{if(m_filelist.empty()){return nullptr;}UploadFileInfo* tempm_filelist.at(0);return temp;
}//删除任务
void uploadtask::delUploadTask()
{//1.取出任务判断该任务的状态如果是上传完成上传失败上传成功该任务是会被删除掉//2.将该任务从列表中移除//3.删除进度条并删除该任务的资源if(isEmpty()){return;}UploadFileInfo* tempm_filelist.at(0);if(temp-uploadStatusUPLOAD_FINISHED||temp-uploadStatusUPLOAD_FAILD||temp-uploadStatusUPLOAF_FILE_EXISTE ){//删除该任务qDebug()删除任务;m_filelist.removeAt(0);//将进度条从布局中移除uploadlayout::getInstant()-getVLayout()-removeWidget(temp-fdp);delete temp-fdp;delete temp;}
}//清空任务列表
void uploadtask::clearList()
{int lenm_filelist.size();for(int i0;ilen;i){UploadFileInfo* tempm_filelist.at(0);m_filelist.removeAt(0);uploadlayout::getInstant()-getVLayout()-removeWidget(temp-fdp);//将进度条从布局中移除delete temp-fdp;delete temp;}
} 设置上传的槽函数
点击 “上传文件 的QListWidgetItem,将文件的上传任务 添加 到 上传队列中。
//设置“上传文件”QListWidgetItem的槽函数
//双击QListWidget窗口中的控件则会发出一个itemDoubleClicked信号
connect(ui-listWidget,QListWidget::itemDoubleClicked,this,[](QListWidgetItem *item){if(item-text()上传文件){addUploadFile();}});//设置“上传”菜单项的槽函数connect(m_uploadAction,QAction::triggered,this,[]{addUploadFile();qDebug()上传;
});//添加上传文件
void myfile::addUploadFile()
{//getOpenFileNames可以获取多个文件的路径QStringList filelistQFileDialog::getOpenFileNames();for(int i0;ifilelist.size();i){//将文件添加到m_uploadtask中int resm_uploadtask-appendUploadTask(filelist[i]);if(res-1){//服务器设置最多只能上传30m大小的文件QMessageBox::warning(this,警告,文件大小大于30m);}}
}
uploadFileAction接口
uploadFileAction从m_uploadtask获取一个UploadFileInfo对象在根据UploadFileInfo对象信2息发送一个 HTTP请求给服务器去验证文件是否存在。
POST http://119.23.41.13:80/md5 HTTP/1.1
Content-Type: application/json{fileName: 111.rtf, //文件名md5: 8274425de767b30b2fff1124ab54abb5,//文件md5值标识文件的唯一性token: 7b4b4922958c5cbb153df2668b714144,//验证用户身份user: zhangsan//用户信息
}客户端根据服务器返回的 code 做出相应的动作。
code:005 //上传的文件已存在别的用户正在上传该文件
code:006 //秒传成功文件已经存在
code:007 // 秒传失败文件不存在需要调用uploadFile上传文件
code:011 //Token 验证失败身份过期 //获取m_uploadtask中的一个上传任务
void myfile::uploadFileAction()
{if(m_uploadtask-isEmpty()){//任务列表为空// qDebug()任务列表为空;return;}UploadFileInfo* uploadFileInfom_uploadtask-takeTask();//先进行快传判断文件是否已经上传成功//封装http请求//如果该文件没有上传则发送请求if(uploadFileInfo-uploadStatusUPLOAD_NOT){uploadFileInfo-uploadStatusUPLOADING;QNetworkRequest request;//从配置文件中获取到ip地址和port端口号QString ipCommon::getInstant()-getConfValue(web_server,ip);QString portCommon::getInstant()-getConfValue(web_server,port);QString url QString(http://%1:%2/md5).arg(ip).arg(port);request.setUrl(QUrl(url));//设置文件类型request.setHeader(QNetworkRequest::ContentTypeHeader,QVariant(application/json));//将data数据以QJson的格式发送给服务器QJsonObject object;object.insert(user, m_logininfo-user());object.insert(token, m_logininfo-token());object.insert(md5,uploadFileInfo-md5);object.insert(fileName,uploadFileInfo-fileName);QJsonDocument doc(object);QByteArray datadoc.toJson();//发送请求// qDebug()data;QNetworkReply* relym_manager-post(request,data);connect(rely,QNetworkReply::readyRead,this,[]{//响应到达,读取所有的数据QByteArray srely-readAll();qDebug() 服务器返回数据: QString(s);//将s数据转换为Json对象QJsonParseError err;QJsonDocument documentQJsonDocument::fromJson(s,err);if(err.error!QJsonParseError::NoError){qDebug()QJson格式错误;return;}//将QJson字符串转换为QJson对象QJsonObject object1;object1document.object();//获取状态码QString value1object1[code].toString();if(value1005){qDebug()文件已经存在;//文件正在上传uploadFileInfo-uploadStatusUPLOAF_FILE_EXISTE;Common::getInstant()-writeRecord(m_logininfo-user(),uploadFileInfo-fileName,value1);m_uploadtask-delUploadTask();return;}if(value1006){uploadFileInfo-uploadStatusUPLOAF_FILE_EXISTE;Common::getInstant()-writeRecord(m_logininfo-user(),uploadFileInfo-fileName,value1);m_uploadtask-delUploadTask();qDebug()妙传成功;}if(value1007){//qDebug()上传文件;//文件没有上传到服务器上需要将文件上传到服务器上uploadFile(uploadFileInfo);}if(value1111){Common::getInstant()-writeRecord(m_logininfo-user(),uploadFileInfo-fileName,value1);qDebug()token验证失败;}});}
} uploadFile接口
uploadFile是发送一个 http请求 将文件中数据发送给服务器服务器会将其进行保存。
POST http://119.23.41.13:80/upload HTTP/1.1
Content-Type: application/json------WebKitFormBoundaryNr0Jm9D3w0GCiG9g //文件边界线
Content-Disposition: form-data; userzhangsan filename111.rtf md58274425de767b30b2fff1124ab54abb5 size7
Content-Type: application/octet-stream文件数据
------WebKitFormBoundaryNr0Jm9D3w0GCiG9g //文件边界线
服务器返回值
code:008
code:009 //将文件上传到服务器上
/*
------WebKitFormBoundaryDQAR0QX1ojAyzAre\r\n
Content-Disposition: form-data; namefile; filenamelogo.png\r\n
Content-Type: image/png\r\n
\r\n
真正的文件内容\r\n
------WebKitFormBoundaryDQAR0QX1ojAyzAre
*/
//将文件内容上传到服务器上
void myfile::uploadFile(UploadFileInfo *uploadFileInfo)
{QFile file(uploadFileInfo-filePath);file.open(QIODevice::ReadOnly | QIODevice::Text);logininfoinstance *login logininfoinstance::getInstant();//getBoundary接口是随机生成一个文件边界线QString boundary m_common-getBoundary();QByteArray data;data.append(boundary);data.append(\r\n);data.append(Content-Disposition: form-data; );data.append(QString(user\%1\ filename\%2\ md5\%3\ size%4).arg(login-user()).arg(uploadFileInfo-fileName).arg(uploadFileInfo-md5).arg(uploadFileInfo-size));data.append(\r\n);data.append(Content-Type: application/octet-stream);data.append(\r\n);data.append(\r\n);//上传中的数据data.append(file.readAll());data.append(\r\n);data.append(boundary);//文件边界线if (file.isOpen()) {file.close();}QString url QString(http://%1:%2/upload).arg(login-ip()).arg(login-port());QNetworkRequest request;request.setUrl(url);request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant(application/json));//发送http请求QNetworkReply *reply m_manager-post(request, data);if (reply NULL) {qDebug() 请求失败;return;}//显示文件上传进度connect(reply, QNetworkReply::uploadProgress, this, [](qint64 bytesSent, qint64 bytesTotal){//bytesSent 上传的字节数//bytesTotal 文件需要上传的总字节数if (bytesTotal ! 0) {//显示进度条(设置进度条)uploadFileInfo-fdp-setValue(bytesSent, bytesTotal);}});connect(reply, QNetworkReply::finished, this, [](){//文件上传完成后if (reply-error() ! QNetworkReply::NoError) {qDebug() reply-errorString();} else {QByteArray sreply-readAll();/*008: 上传成功009: 上传失败*///响应到达,读取所有的数据// qDebug() 服务器返回数据: QString(s);//将s数据转换为Json对象QJsonParseError err;QJsonDocument documentQJsonDocument::fromJson(s,err);if(err.error!QJsonParseError::NoError){qDebug()QJson格式错误;return;}//将QJson字符串转换为QJson对象QJsonObject object1;object1document.object();//获取状态码QString value1object1[code].toString();if (value1 008) {qDebug() 上传成功;uploadFileInfo-uploadStatusUPLOAD_FINISHED;getFileCount(Normal);} else if (value1 009) {uploadFileInfo-uploadStatusUPLOAD_FAILD;qDebug() 上传失败;}//将传输记录记录到文件中Common::getInstant()-writeRecord(login-user(),uploadFileInfo-fileName,value1);// writeRecord(QString user, QString fileName, QString code, QString path)}m_uploadtask-delUploadTask();reply-deleteLater();});
} 定时上传文件
定义一个定时器定时器每0.5秒 调用一次uploadFileAction函数 //设置每0.5秒调用uploadFileActionm_uploadTimer.start(500);connect(m_uploadTimer,QTimer::timeout,this,[](){uploadFileAction();});
进度条的设计
自定义一个进度条类型filedataProgress 包括filedataProgress.h filedataProgress.cppfiledataProgress.ui 文件.
filedataProgress.ui界面设计 //filedataProgress.cpp文件
//设置文件名
void filedataProgress::setName(QString name)
{ui-label-setText(name);
}
//设置进度条数据
void filedataProgress::setValue(int value,int maxValue)
{ui-progressBar-setValue(value*100/maxValue);
}当上传任务添加到上传列表时就将进度条显示到 上传列表中等待客户端上传文件。
在uploadFile接口 中需要设置 QNetWorkReply的uploadProgress信号将上传的进度显示到进度条上。。QNetWorkReply每 当上传一次文件数据则会发出uploadProgress信号
注意 bytesTotal 不能为 0如果为 0则会崩溃。 //显示文件上传进度connect(reply, QNetworkReply::uploadProgress, this, [](qint64 bytesSent, qint64 bytesTotal){//bytesSent 上传的字节数//bytesTotal 文件需要上传的总字节数if (bytesTotal ! 0) {//显示进度条(设置进度条)uploadFileInfo-fdp-setValue(bytesSent, bytesTotal);}});