C++ Post上传文件到Django
Django Api:
def uploadfile(request):
if request.method == "POST": # 请求方法为POST时,进行处理
myFile = request.FILES.get("myfile", None) # 获取上传的文件,如果没有文件,则默认为None
if not myFile:
return HttpResponse("no files for upload!")
destination = open(os.path.join("F:\\upload", myFile.name), 'wb+') # 打开特定的文件进行二进制的写操作
for chunk in myFile.chunks(): # 分块写入文件
destination.write(chunk)
destination.close()
return HttpResponse("upload over!")
注意要在对应web项目下的urls.py里把这个方法发布出去(网址),访问这个网址使用api
如果要请求结束后发送一个json的返回值可以这么写
return HttpResponse(json.dumps(request, ensure_ascii = False))
这里的result是一个json格式的字典,比如:
result = {
fileName:name
code : 0
}
c++创建Http Post请求发送文件
#pragma once
#include <iostream>
using namespace std;
typedef size_t(*pfn_write_data)(char *buffer, size_t size, size_t nitems, void *pattach);
//优点:不需要依赖第三方库,缺点:功能单一如:不支持301跳转
class CHttpConnect
{
public:
CHttpConnect();
~CHttpConnect(void);
static string HttpPost(std::string host, std::string post);
static string HttpPostFile(std::string host, std::string post, std::string filename);
static string HttpGet(std::string host);
static string GetFileContext(std::string filename);
static void HttpDownload(std::string host, pfn_write_data pwrite_data, void* pattach = NULL);
private:
static short ParseUrl(std::string& host, std::string& path);
static string SocketHttp(std::string host, std::string request, short port, pfn_write_data pwrite_data = NULL, void* pattach = NULL);
static string SocketHttp1(std::string host, std::string request, short port, pfn_write_data pwrite_data = NULL, void* pattach = NULL);
};
cpp文件
#include "CHttpConnect.h"
#include <WinSock.h>
#include <stdio.h>
#include <sstream>
#include <iostream>
#include <algorithm>
#ifdef WIN32
#pragma comment(lib,"ws2_32.lib")
#endif
CHttpConnect::CHttpConnect()
{
}
CHttpConnect::~CHttpConnect(void)
{
}
short CHttpConnect::ParseUrl(std::string& host, std::string& path)
{
short nPort = 80;
//处理主机域名不能带http开头
int pos = host.find("http://");
if (pos >= 0)
{
int endPos = host.find("/", pos + 7);
if (endPos >= 0)
{
path = host.substr(endPos, host.length() - endPos);
host = host.substr(pos + 7, endPos - pos - 7);
}
else
{
host = host.substr(pos + 7, host.length() - pos - 7);
}
pos = host.find(":");
if (pos >= 0)
{
string sPort = host.substr(pos + 1, host.length() - pos - 1);
nPort = atoi(sPort.c_str());
host = host.substr(0, pos);
}
}
else
{
int endPos = host.find("/");
if (endPos >= 0)
{
path = host.substr(endPos, host.length() - endPos);
host = host.substr(0, endPos);
}
pos = host.find(":");
if (pos >= 0)
{
string sPort = host.substr(pos + 1, host.length() - pos - 1);
nPort = atoi(sPort.c_str());
host = host.substr(0, pos);
}
}
return nPort;
}
std::string CHttpConnect::SocketHttp(std::string host, std::string request, short port, pfn_write_data pwrite_data, void* pattach)
{
#ifdef WIN32
//此处一定要初始化一下,否则gethostbyname返回一直为空
WSADATA wsa = { 0 };
WSAStartup(MAKEWORD(2, 2), &wsa);
#endif
int sockfd;
struct sockaddr_in address;
struct hostent *server;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
address.sin_family = AF_INET;
address.sin_port = htons(port);
server = gethostbyname(host.c_str());
memcpy((char *)&address.sin_addr.s_addr, (char*)server->h_addr, server->h_length);
if (-1 == connect(sockfd, (struct sockaddr *)&address, sizeof(address))) {
//ASSERT("连接失败");
return "连接失败";
}
#ifdef WIN32
send(sockfd, request.c_str(), request.size(), 0);
#else
write(sockfd, request.c_str(), request.size());
#endif
char buf[1024];
int actual = -1;
bool checkHttpHead = true;
LPCSTR lpLine = NULL;
std::stringstream out;
#ifdef WIN32
while (actual = recv(sockfd, buf, 1024, 0))
#else
while (actual = read(sockfd, buf, 1024))
#endif
{
if (checkHttpHead)
{
if ((lpLine = strstr(buf, "\r\n\r\n")))
{
int offset = lpLine - buf + strlen("\r\n\r\n");//出现的指针减去起始指针得到长度
if (pwrite_data == NULL) {
out << string(buf + offset, actual - offset) << endl;//数据写到缓存
string str_result = out.str();
//cout << str_result << endl;
}
else
pwrite_data(buf + offset, 1, actual - offset, pattach);
checkHttpHead = false;//http头读取完毕
lpLine = NULL;//指针放空
}
continue;
}
if (pwrite_data == NULL) {
out << string(buf, actual) << endl;//数据写到缓存
}
else {
pwrite_data(buf, 1, actual, pattach);
}
}
#ifdef WIN32
closesocket(sockfd);
//此处一定要初始化一下,否则gethostbyname返回一直为空
::WSACleanup();
#else
close(sockfd);
#endif
string str_result = out.str();
return str_result;
}
std::string CHttpConnect::SocketHttp1(std::string host, std::string request, short port, pfn_write_data pwrite_data, void* pattach)
{
#ifdef WIN32
//此处一定要初始化一下,否则gethostbyname返回一直为空
WSADATA wsa = { 0 };
WSAStartup(MAKEWORD(2, 2), &wsa);
#endif
int sockfd;
struct sockaddr_in address;
struct hostent *server;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
address.sin_family = AF_INET;
address.sin_port = htons(port);
server = gethostbyname(host.c_str());
memcpy((char *)&address.sin_addr.s_addr, (char*)server->h_addr, server->h_length);
if (-1 == connect(sockfd, (struct sockaddr *)&address, sizeof(address))) {
return "连接失败";
}
#ifdef WIN32
send(sockfd, request.c_str(), request.size(), 0);
#else
write(sockfd, request.c_str(), request.size());
#endif
char buf[1024];
int actual = -1;
bool checkHttpHead = true;
LPCSTR lpLine = NULL;
std::stringstream out;
#ifdef WIN32
while (actual = recv(sockfd, buf, 1024, 0))
#else
while (actual = read(sockfd, buf, 1024))
#endif
{
if (checkHttpHead)
{
if ((lpLine = strstr(buf, "\r\n\r\n")))
{
int offset = lpLine - buf + strlen("\r\n\r\n");//出现的指针减去起始指针得到长度
if (pwrite_data == NULL) {
out << string(buf + offset, actual - offset) << endl;//数据写到缓存
string str_result = out.str();
//cout << str_result << endl;
}
else {
pwrite_data(buf + offset, 1, actual - offset, pattach);
}
checkHttpHead = false;//http头读取完毕
lpLine = NULL;//指针放空
}
continue;
}
if (pwrite_data == NULL) {
out << string(buf, actual) << endl;//数据写到缓存
#ifdef WIN32
closesocket(sockfd);
//此处一定要初始化一下,否则gethostbyname返回一直为空
::WSACleanup();
#else
close(sockfd);
#endif
string str_result = out.str();
return str_result;
}
}
#ifdef WIN32
closesocket(sockfd);
//此处一定要初始化一下,否则gethostbyname返回一直为空
::WSACleanup();
#else
close(sockfd);
#endif
string str_result = out.str();
return str_result;
}
// 文件的二进制数据在body里面
std::string CHttpConnect::HttpPost(std::string host, std::string post)
{
string path;
short nPort = ParseUrl(host, path);
//POST请求方式
std::stringstream stream;
stream << "POST " << path;
stream << " HTTP/1.0\r\n";
stream << "Host: " << host << "\r\n";
stream << "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3\r\n";
stream << "Content-Type:application/x-www-form-urlencoded\r\n";
stream << "Content-Length:" << post.length() << "\r\n";
stream << "Connection:close\r\n\r\n";
stream << post;
return SocketHttp(host, stream.str(), nPort);
}
std::string CHttpConnect::HttpGet(std::string host)
{
//GET请求方式
std::stringstream stream;
string path;
short nPort = ParseUrl(host, path);
stream << "GET " << path;
stream << " HTTP/1.0\r\n";
stream << "Host: " << host << "\r\n";
stream << "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3\r\n";
stream << "Connection:close\r\n\r\n";
return SocketHttp(host, stream.str(), nPort);
}
void CHttpConnect::HttpDownload(std::string host, pfn_write_data pwrite_data, void* pattach)
{
//GET请求方式
std::stringstream stream;
string path;
short nPort = ParseUrl(host, path);
stream << "GET " << path;
stream << " HTTP/1.0\r\n";
stream << "Host: " << host << "\r\n";
stream << "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3\r\n";
stream << "Connection:close\r\n\r\n";
SocketHttp(host, stream.str(), nPort, pwrite_data, pattach);
}
// 文件的数据在FILES里,但是这个方式好像有点问题,发送结束后程序不结束
string CHttpConnect::HttpPostFile(std::string host, std::string post, string filename)
{
string path;
short nPort = ParseUrl(host, path);
//POST请求方式
std::string header("");
header += "POST ";
header += path;
header += " HTTP/1.1\r\n";
header += "User-Agent: Mozilla/4.0\r\n";
header += "Host: ";
header += host;
header += "\r\n";
header += "Pragma: no-cache\r\n";
header += "Accept: */*\r\n";
header += "Content-Type: multipart/form-data; boundary=----------------------------64b23e4066ed\r\n";
std::string content("");
content += "------------------------------64b23e4066ed\r\n";
content += "Content-Disposition: form-data; name='id'\r\n\r\n";
content += "3365863\r\n";
content += "------------------------------64b23e4066ed\r\n";
content += "Content-Disposition: form-data; name=myfile; filename=";
content += filename;
content += "\r\n";
content += "Content-Type: custom\r\n\r\n";
content += post;
content += "\r\n------------------------------64b23e4066ed--\r\n";
char temp[64] = { 0 };
sprintf(temp, "Content-Length: %d\r\n\r\n", content.length());
header += temp;
std::string str_http_request = header + content;
return SocketHttp1(host, str_http_request, nPort);
}
string CHttpConnect::GetFileContext(string filename)
{
const char *name = filename.c_str();
FILE *fp = std::fopen(name, "rb");
if (fp) {
string contexts;
fseek(fp, 0, SEEK_END);
contexts.resize(ftell(fp));
rewind(fp);
fread(&contexts[0], 1, contexts.size(), fp);
fclose(fp);
return contexts;
}
throw(errno);
}
int main(int argc, char* argv[])
{
string path = "C:\\Users\\hp\\Desktop\\cailiao\\4.jpg";
string post = CHttpConnect::GetFileContext(path);
string result = CHttpConnect::HttpPostFile("127.0.0.1:8111/blog/uploadfile", post,"4.jpg");
//string result = CHttpConnect::HttpPost("127.0.0.1:8111/blog/uploadfile", post);
std::cout << result << std::endl;
return 0;
}
结束
附加
Qt 发送Post
发送Json
QNetworkAccessManager *manage = QNetworkAccessManager ();
QNetRequest request;
request.setUrl(QUrl(…));
QHttpMultipart * multipart = new QHttpMultipart (QHttpMultipart::FormDataType);
QHttpPart metapart;
metapart.setHeader(QNetworkRequest::ContextTypeHeader,“application/json”);
metaport.setHeader(QNetworkRequest::ContextTypeHeader,QVariant(“form-data;name=“tool_name””));
metaport.setBody(“seagullxxx”);
multipart.append(metapart);
manager->post(request,multipart);
发送文件直接发QByteArray
数据会发送到body中,用request.body取
byte = request.body
file = open(os.path.join(文件路径+名称,"wb+"))
file.write(byte)
file.close()
发送文件
转载链接
我没有写上传普工表单的部分,直接写的上传文件可以,不知道有什么影响
简单的例子:
头文件
#ifndef HTTPPOSTFILE_H
#define HTTPPOSTFILE_H
#include <QHttpMultiPart>
#include <QMainWindow>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
QT_BEGIN_NAMESPACE
namespace Ui {
class HttpPostFile;
}
QT_END_NAMESPACE
class HttpPostFile : public QMainWindow
{
Q_OBJECT
public:
HttpPostFile(QWidget *parent = nullptr);
~HttpPostFile();
void startPost();
public slots:
void finished(QNetworkReply *);
void finished();
private slots:
void on_pushButton_clicked();
private:
Ui::HttpPostFile *ui;
QNetworkReply *reply;
QNetworkAccessManager *manager;
};
#endif // HTTPPOSTFILE_H
cpp文件:
#include "HttpPostFile.h"
#include "ui_HttpPostFile.h"
#include <QDebug>
#include <QFile>
#include <QUuid>
HttpPostFile::HttpPostFile(QWidget *parent) : QMainWindow(parent), ui(new Ui::HttpPostFile)
{
ui->setupUi(this);
manager = new QNetworkAccessManager();
}
HttpPostFile::~HttpPostFile()
{
delete ui;
}
void HttpPostFile::startPost()
{
QString BOUNDARY = QUuid::createUuid().toString();
QNetworkRequest request = QNetworkRequest(QUrl("http://127.0.0.1:8111/blog/uploadfile"));
QFile *file = new QFile("C:\\Users\\hp\\Desktop\\cailiao\\4.jpg");
file->open(QIODevice::ReadOnly);
QByteArray sb = QByteArray();
sb.append("--" + BOUNDARY + "\r\n");
sb.append(QString("Content-Disposition: form-data;name=\"") + "myfile"
+ QString("\";filename=\"") + "45.jpg" + QString("\"") + QString("\r\n"));
sb.append("\r\n");
sb.append(file->readAll());
sb.append("\r\n");
sb.append("--" + BOUNDARY + "\r\n");
request.setRawHeader(QString("Content-Type").toLatin1(),
QString("multipart/form-data;boundary=" + BOUNDARY).toLatin1());
request.setRawHeader(QString("Content-Length").toLatin1(),
QString::number(sb.length()).toLatin1());
reply = manager->post(request, sb);
manager->get(request);
connect(reply, SIGNAL(finished()), this, SLOT(finished()));
}
void HttpPostFile::finished(QNetworkReply *rp)
{
qDebug() << rp->readAll();
}
void HttpPostFile::finished()
{
QNetworkReply *rp = qobject_cast<QNetworkReply *>(sender());
qDebug() << rp->readAll();
}
void HttpPostFile::on_pushButton_clicked()
{
startPost();
}
//注:还是用Qt写好一点,把那些烦人的创建socket请求全都封装好了。c++真是麻烦。