libevent上传和下载文件

记录使用libevent实现上传和下载文件

上传采用表单的形式

该函数只能完成表单上传一个文件的功能

void apiUploadFile(struct evhttp_request* req, void* arg) {
    if(!checkCmdAndUrl(req , EVHTTP_REQ_POST)) {
        return;
    }
    int nCode = -1;
    std::string strResp;
    // 消息报头
	evkeyvalq *headers = evhttp_request_get_input_headers(req);
	std::cout << "====== headers ======" << std::endl;
	for (evkeyval *p = headers->tqh_first; p != NULL; p = p->next.tqe_next)
	{
		cout << p->key << ":" << p->value << endl;
	}
    std::cout << "======headers end====\n";
    char* pBoundary = (char*)evhttp_find_header(headers , "Content-Type");
    pBoundary = strstr(pBoundary , "boundary=");
    pBoundary += 9;
    printf("pBoundary: %s\n", pBoundary);    // 需要提取boundary
    char strtemp[260] = {0};
    char name[256] = {0};
    char fileName[256] = {0};
    char filePath[256] = {0};
    do
    {
        if(pBoundary != NULL) {
            int iBoundaryLen = strlen(pBoundary);
            size_t post_size = evbuffer_get_length(req->input_buffer);  //获取数据长度
            if(post_size > 0) {
                char *search = (char*)(evbuffer_pullup(req->input_buffer, -1));
                char* pSearch = search;
                char* end = search + post_size;
                pSearch = strstr(pSearch, "\r\n");  // 跳过第一行boundary
                pSearch += 4;
                // name 
                char* pName = strstr(pSearch , "name=");
                pName += 6;
                char* ptemp = strstr(pName , ";");
                snprintf(name , ptemp - pName , "%s" , pName);
                printf("pName : %s\n" , name);
                // file name
                pName = strstr(pSearch , "filename=");
                pName += 10;
                ptemp = strstr(pName , "\r\n");
                snprintf(fileName , ptemp - pName , "%s" , pName);
                printf("filename = %s\n" , fileName);
                //
                printf("body :\n%s\n" , search);
                char* pstart = strstr(search, "\r\n\r\n");
                char *pend = NULL;
                if(pstart != NULL && pstart < end) {
                    pstart += 4;
                    sprintf(strtemp,"\r\n%s--\r\n\r\n", pBoundary);
                    int file_size = post_size - (pstart - search) - strlen(strtemp); // 要剪掉最后boundary的长度
                    // 读取文件内容
                    sprintf(filePath , "/data/project/work/config/update/%s" , fileName);
                    FILE* fp = fopen(filePath , "w");
                    fwrite(pstart , file_size , 1 , fp);
                    fclose(fp);
                }
            }
        }
    }while(0);
    nCode = -1;
    rapidjson::StringBuffer s;
    rapidjson::Writer<rapidjson::StringBuffer> writer(s);
    writer.StartObject();
    writer.Key("code");  writer.Int(nCode);
    writer.Key("msg");   writer.String(strResp.c_str());
    writer.EndObject();
    SendJsonReponse(req , s.GetString());
}

下载

void apiDownFile(struct evhttp_request* req, void* arg) {
    if(!checkCmdAndUrl(req , EVHTTP_REQ_GET)) {
        return;
    }
    int nCode = -1;
    std::string strResp;

    //消息报头
	evkeyvalq* headers = evhttp_request_get_input_headers(req);
	cout << "======headers: =======\n";
	for (evkeyval* p = headers->tqh_first; p != NULL; p = p->next.tqe_next) {
		std::cout << p->key << ":" << p->value << std::endl;
	}

    //请求正文(GET=NULL, POST有表单信息)
	evbuffer* inbuf = evhttp_request_get_input_buffer(req);
	char buf[1024] = { 0 };
	cout << "=============inbuf==============" << endl;
	while (evbuffer_get_length(inbuf))
	{
		int n = evbuffer_remove(inbuf, buf, sizeof(buf) - 1);
		if (n > 0) 
		{
			buf[n] = '\0';
			cout << buf << endl;
		}
	}

    std::string filepath = "/data/project";
    const char* uri = evhttp_request_get_uri(req);
    filepath += uri;
    //消息报头
	evkeyvalq* outhead = evhttp_request_get_output_headers(req);
    // 支持图片,js,css,下载普通zip文件
	// 获取文件的后缀名
	// ./root/index.html
	int pos = filepath.rfind('.');
    std::string postfix = filepath.substr(pos + 1, filepath.size() - (pos + 1));
    printf("filepath: %s , postfix: %s\n" , filepath.c_str() , postfix.c_str());
    if (postfix == "jpg"|| postfix == "gif"|| postfix == "png")
	{
		string tmp = "image/" + postfix;
		evhttp_add_header(outhead, "Content-Type", tmp.c_str());
	}
	else if (postfix == "zip")
	{
		evhttp_add_header(outhead, "Content-Type", "application/zip");
	}
	else if (postfix == "html") 
	{
		//evhttp_add_header(outhead, "Content-Type", "text/html; charset=UTF8");
		evhttp_add_header(outhead, "Content-Type", "text/html");
	}
	else if (postfix == "css")
	{
		evhttp_add_header(outhead, "Content-Type", "text/css");
	}
	else if (postfix == "js")
	{
		evhttp_add_header(outhead, "Content-Type", "text/js");
	}
    else if (postfix == "log")
	{
		evhttp_add_header(outhead, "Content-Type", "text/plain");
	}

//           类型	描述	典型示例
// text	    表明文件是普通文本,理论上是人类可读	text/plain, text/html, text/css, text/javascript
// image	表明是某种图像。不包括视频,但是动态图(比如动态 gif)也使用 image 类型	image/gif, image/png, image/jpeg, image/bmp, image/webp, image/x-icon, image/vnd.microsoft.icon
// audio	表明是某种音频文件	audio/midi, audio/mpeg, audio/webm, audio/ogg, audio/wav
// video	表明是某种视频文件	video/webm, video/ogg
// application	表明是某种二进制数据	application/octet-stream, application/pkcs12, application/vnd.mspowerpoint, application/xhtml+xml, application/xml, application/pdf
    
    //读取html文件返回正文
	FILE* fp = fopen(filepath.c_str(), "r");
	if (!fp)
	{
		evhttp_send_reply(req , HTTP_NOTFOUND , "" , 0);
		return;
	}

    evbuffer* outbuf = evhttp_request_get_output_buffer(req);
    for (;;) {
		int len = fread(buf, 1, sizeof(buf), fp);
		if (len <= 0) break;
		evbuffer_add(outbuf, buf, len);
	}
	fclose(fp);
	evhttp_send_reply(req , HTTP_OK , "" , outbuf);
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值