Qt通过HTTP POST上传文件

Posted 朝闻道

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Qt通过HTTP POST上传文件相关的知识,希望对你有一定的参考价值。

本文使用Qt Creator用HTTP POST的方法上传文件,并给出一个上传文件的例程。

 

本文主要客户端,所以对于服务器端程序编写的描述会比较简略

服务器使用Django编写,django服务器接收文件的方法在文章http://www.cnblogs.com/fnng/p/3740274.html中有较为清晰的讲解,我搭建的服务器端程序除了没有网页客户端以及部分变量名称不同以外,基本上与这篇文章的服务器搭建过程一样。

如果服务器端程序发生变化,这篇文章后面给出的客户端例程可能就不再适用。因此如果运行客户端程序之后发现服务器端不能接收到文件,不要直接认为这篇文章给出的客户端例程是错误的,也可能是其他问题导致的。

在制作程序时,我并没有尝试上传大文件、同时上传多个文件以及文件名中包含中文这三种情况。因此在这三种情况下程序很有可能出现BUG。

 

示例程序链接:http://pan.baidu.com/s/1i5NWsHR

 

1.      服务器端

服务器端程序基本参照http://www.cnblogs.com/fnng/p/3740274.html。这里直接贴出代码,搭建过程以及代码描述等就不进行说明了。

 

disk/views.py:

from django.shortcuts import render,render_to_response

from django.http import HttpResponse

from django import forms

from .models import User

import os

 

# Create your views here.

class UserForm(forms.Form):

    username=forms.CharField()

    upload_file=forms.FileField()

 

def index(request):

    if request.method=="POST":

        uf=UserForm(request.POST,request.FILES)

        print(str(request.POST))

        print(str(request.FILES))

        if uf.is_valid():

            username=uf.cleaned_data[\'username\']

            upload_file=uf.cleaned_data[\'upload_file\']

 

            dir_name=\'./upload/\'+username

            if os.path.exists(dir_name)==False:

                os.mkdir(dir_name)

 

            user=User()

            user.username=username

            user.upload_file=upload_file

            user.save()

            return HttpResponse(\'upload ok!\')

    else:

        uf=UserForm()

return HttpResponse(\'000!\')

 

disk/models.py:

from django.db import models

 

# Create your models here.

 

def content_file_name(instance,filename):

    s=\'/\'.join([\'upload\',instance.username,filename])

    return s

 

class User(models.Model):

 

    username=models.CharField(max_length=30)

    upload_file=models.FileField(upload_to=content_file_name)

 

    def __unicode__(self):

        return self.username

 

disk/urls.py:

from django.conf.urls import url

from . import views

 

urlpatterns=[

    #View the information of user.

    url(r\'^$\',views.index,name=\'index\'),

]

 

2.         客户端程序应该上传的数据

客户端程序在向服务器端上传文件时,不能只上传文件的内容。如果上传的数据中只有文件的内容,那么服务器端是不能正常接收到文件的。客户端上传的内容应该包括普通的表单数据、文件头部以及文件内容三大部分,并对需要传输的数据进行规范化地拼接,按照特定的格式上传数据。

对于我用django制作的这个服务器端程序来说,客户端需要上传一个name为username的普通数据,以及一个name为upload_file的文件数据。下面的代码将需要发送的数据进行拼接并使用POST请求将数据发送给服务器。

3.         新建工程过程中需要注意的地方

在pro文件中要加上QT += network 如果不添加会报错

在代码文件的最前面添加包含 #include 。(不添加的话程序会编译失败)我自己在学习使用Qt进行HTTP通信时发现网上的很多文章在贴出代码时并没有贴出前面的#include部分,导致我花了很长时间去找需要引用的文件。

4.         客户端上传文件的代码

 

void UpLoadForm(QString Path,QMap<</span>QString,QString> params,QStringfileFormName,QFile *uploadFile,QString newFileName){

    QString BOUNDARY=QUuid::createUuid().toString();

    QByteArray sb=QByteArray();

 

    //先上传普通的表单数据

    for(QMap<</span>QString,QString>::Iteratort=params.begin();t!=params.end();t++){

        sb.append("--"+BOUNDARY+"\\r\\n");

        sb.append(QString("Content-Disposition: form-data;name=\\"")+t.key()+QString("\\"")+QString("\\r\\n"));

        sb.append("\\r\\n");

        sb.append(t.value()+"\\r\\n");

    }

    //上传文件的头部

    sb.append("--"+BOUNDARY+"\\r\\n");

    sb.append(QString("Content-Disposition: form-data;name=\\"")+fileFormName+QString("\\";filename=\\"")+newFileName+QString("\\"")+QString("\\r\\n"));

    sb.append("\\r\\n");

    //上传文件内容

    if(!uploadFile->open(QIODevice::ReadOnly)){

        return;

    }

    sb.append(uploadFile->readAll());

    sb.append("\\r\\n");

    sb.append("--"+BOUNDARY+"\\r\\n");

    //编辑HTTP头部

    QNetworkAccessManager *_uploadManager=new QNetworkAccessManager();

    QNetworkRequest request=QNetworkRequest(QUrl(Path));

    request.setRawHeader(QString("Content-Type").toLatin1(),QString("multipart/form-data;boundary="+BOUNDARY).toLatin1());

    request.setRawHeader(QString("Content-Length").toLatin1(),QString::number(sb.length()).toLatin1());

    //执行post请求

_uploadManager->post(request,sb);

}

5.         编写main函数调用前面上传文件的代码,完成测试。

在这里,我们提交了一个name为username的普通表单数据,它的值为10005。我们同时还提交了一个name为upload_file的文件数据。我们上传了本地的”:/Untitled.png”文件,上传成功之后服务器会接收到这个文件,保存时命名为”1A.png”

int main(int argc, char *argv[])

{

    QCoreApplication a(argc, argv);

 

    QString path="http://192.168.252.2:8000/disk/"; //服务器的url

    QMap<</span>QString,QString> params_send; //上传的普通参数 在本程序中 需要上传一个普通参数为"username"

    params_send.insert("username","10005");

    QString fileFormName="upload_file"; //上传文件表单中的名字

 

    QFile *file=new QFile(":/Untitled.png");

 

    QString newFileName="1A.png";

    UpLoadForm(path,params_send,fileFormName,file,newFileName);

 

    return a.exec();

}

 

6.         效果

Qt通过HTTP <wbr>POST上传文件

 

我们把这张图片”untitled.png”上传给服务器

 

 Qt通过HTTP <wbr>POST上传文件

 

 

服务器接收到了客户端发来的图片,表单数据中username=10005,所以新建了一个文件夹”10005”,将接收到的图片保存在了这个文件夹中并命名为”1A.png”

7.         参考资料

http://www.cnblogs.com/fnng/p/3740274.html

https://forum.qt.io/topic/11086/solved-qnetworkaccessmanager-uploading-files

http://blog.csdn.net/lmj623565791/article/details/23781773

 

如果发现问题欢迎在下面留言或私信我

 

http://blog.sina.com.cn/s/blog_15d207b300102xvqz.html

以上是关于Qt通过HTTP POST上传文件的主要内容,如果未能解决你的问题,请参考以下文章

在 Qt4 上使用 POST 方法上传文件

java客户端通过http发送POST请求上传文件

使用 Web 表单通过 HTTP POST 上传文件的最佳方式是啥?

JAVA模拟HTTP post请求上传文件

HTTP POST请求报文格式分析与Java实现文件上传

QHttpMultiPart 上传多个文件