libevent实现图片的上传和下载

上传图片

void UploadFile(struct evhttp_request* req, void* arg)
{
	if (req == nullptr)
	{
		printf("input params is nullptr.\n");
		return;
	}
	if (evhttp_request_get_command(req) == EVHTTP_REQ_OPTIONS) {
		struct evbuffer* buf;
		buf = evbuffer_new();
		evbuffer_add_printf(buf, "111");
		MyHttpServer* pService = MyHttpServer::GetInstance();
		pService->SendReply((evhttp_request*)req, HTTP_OK, nullptr, buf);
		return;
	}
	if (evhttp_request_get_command(req) == EVHTTP_REQ_POST)
	{
		struct evkeyvalq params = { 0 };
		MyHttpServer* pService = MyHttpServer::GetInstance();
		const char* path = pService->find_http_path(req, &params);
		string m_strPath = path;
		if (m_strPath != "/Power/upload")
		{
			cout << "wrong path\n";
			return;
		}
			int boundarylength = 0;
			struct evkeyvalq http_query_post;
			int buffer_data_len = EVBUFFER_LENGTH(req->input_buffer);
			char* post_data = new char[buffer_data_len + 1];
			memset(post_data, 0, buffer_data_len + 1);
			memcpy(post_data, EVBUFFER_DATA(req->input_buffer), buffer_data_len);
			string data1 = post_data;
			string filename;
			int nPos = 0;
			smatch result;
			//按逗号分割
			stringstream subStrSplit(data1);
			string temp;
			vector<string>v;
			//获取接口
			while (getline(subStrSplit, temp, ';')) {
				v.push_back(temp);
			}
			const std::string strValueReg = "\"(.*)\"";
			//提取值
			for (auto& it : v) {
				nPos = it.find("=");
				if (nPos != string::npos) {
					string strLeft = it.substr(0, nPos);
					string strRight = it.substr(nPos + 1, it.length() - nPos);


					regex reg_Realm(strValueReg);
					if (regex_search(strRight, result, reg_Realm)) {

						if (strLeft.find("filename") != string::npos) {
							filename = result[1];
						}
					}

				}
			}

			//获取文件名称filename="a"
			filename = UTF8ToGBK(filename.c_str());
			int var = 0;
			int count = 0;
			char* data = NULL;
			for (var = 0; var < buffer_data_len; var++)
			{
				if (post_data[var] == '\n')
				{
					++count;
					if (count == 4)// 找到文件头
					{
						data = &post_data[var];
						break;
					}
					if (count == 1) {
						boundarylength = var;
					}
				}
			}
			FILE* file = fopen(filename.c_str(), "wb+");//&fname_buf[10]这个是提取的文件名
			if (file == NULL) //判断如果文件指针为空
			{
				printf("File cannot open! ");
			}
			else {
				int fileLen = buffer_data_len - var - 1 - boundarylength;
				fwrite(data + 1, 1, fileLen, file);
				fclose(file);
			}


			delete[] post_data;

			struct evbuffer* evbuf = evbuffer_new();
			if (!evbuf) {
				printf("create evbuffer failed!\n");
				return;
			}

			Json::Value rootRes;
			rootRes["code"] = Json::Value(200);
			rootRes["msg"] = Json::Value("上传成功");
			rootRes["url"] = Json::Value(filename.c_str());
			struct evbuffer* buf;
			buf = evbuffer_new();
			string strJson = rootRes.toStyledString();
			evbuffer_add_printf(buf, GBKToUTF8(strJson.c_str()).c_str());
			pService = MyHttpServer::GetInstance();
			pService->SendReply((evhttp_request*)req, HTTP_OK, nullptr, buf);
	}
}

图片上传的原理

在这里插入图片描述
post传输图片文件的原始报文如下,首先通过正则表达式匹配找到文件名。找到文件名后定位图片文件流的开始。代码是通过搜索换行符来确定图片文件流的位置。从图片可以看出,从Boundary开始,第四个换行符+1就是图片流的起点。图片流的长度是req->input_buffer的长度减去Boundary到第四个换行符的长度减去尾部的Boundary的长度。这个长度即是图片流的实际长度。

图片下载

evhttp_set_gencb(httpd, DownLoadFile, NULL);

void DownLoadFile(struct evhttp_request* req, void* arg)
{
	if (req == nullptr)
	{
		printf("input params is nullptr.\n");
		return;
	}
	if (evhttp_request_get_command(req) == EVHTTP_REQ_OPTIONS) {
		struct evbuffer* buf;
		buf = evbuffer_new();
		evbuffer_add_printf(buf, "111");
		MyHttpServer* pService = MyHttpServer::GetInstance();
		pService->SendReply((evhttp_request*)req, HTTP_OK, nullptr, buf);
	}
	if (evhttp_request_get_command(req) == EVHTTP_REQ_GET)
	{

		struct evkeyvalq params = { 0 };
		MyHttpServer* pService = MyHttpServer::GetInstance();
		const char* path = pService->find_http_path(req, &params);
		string m_strPath = UTF8ToGBK(acl_url_decode(path));
		string filename = m_strPath.substr(1, m_strPath.length() - 1);
		if (!m_strPath.empty())
		{
			FILE* fp = fopen(filename.c_str(), "rb");
			if (!fp)
			{
				evhttp_send_reply(req, HTTP_NOTFOUND, "", 0);
				return;
			}
			char buf[1024] = { 0 };

			evbuffer* outbuf = evhttp_request_get_output_buffer(req);
			for (;;)
			{
				int len = fread(buf, 1, 1024, fp);
				if (len <= 0)break;
				evbuffer_add(outbuf, buf, len);
			}
			fclose(fp);

			evhttp_add_header(req->output_headers, "Content-Type", "image/png");
			evhttp_add_header(req->output_headers, "Access-Control-Allow-Origin", "*");
			evhttp_add_header(req->output_headers, "Access-Control-Allow-Methods", "POST,GET,OPTIONS");
			evhttp_add_header(req->output_headers, "Access-Control-Allow-Credentials", "true");
			evhttp_add_header(req->output_headers, "Access-Control-Allow-Headers", "authorization,Origin,Content-Type,Accept,token,X-Requested-With");

			evhttp_send_reply(req, HTTP_OK, "", outbuf);
			return;
		}


	}



}

定位接口token

BOOLFindToken(struct evhttp_request* pstReq)
{
	struct evkeyvalq* headers = evhttp_request_get_input_headers(pstReq);
	// 获取请求标头
	const char* token111 = evhttp_find_header(headers, "token");
	if (token111 == NULL)
	{
		return FALSE;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值