解析Content-Type: multipart/form-data格式数据

本文介绍了一个C语言实现的解析multipart/form-data格式数据的方法,通过两个函数分别获取boundary和解析具体字段,适用于处理PHP发送的数据。

经常要处理php端发过来的Content-Type: multipart/form-data数据,写两个函数处理下这个数据好。

2014-1-24

发现有个Bug(错误)!!!!


Content-Type: multipart/form-data; boundary=----------------------------aa14712544ce
 
------------------------------aa14712544ce
Content-Disposition: form-data; name="subject"
 
【186期】邂逅青岛,还未离开就想再见
------------------------------aa14712544ce
Content-Disposition: form-data; name="html"
 
Html/78/186soFksp7820130730_f7dJVlDX.html
------------------------------aa14712544ce
Content-Disposition: form-data; name="email"
 
12477511147@qq.com
------------------------------aa14712544ce
Content-Disposition: form-data; name="magid"
 
78
------------------------------aa14712544ce
Content-Disposition: form-data; name="number"
 
186
------------------------------aa14712544ce
Content-Disposition: form-data; name="nick"
 
MyTrip
------------------------------aa14712544ce--


#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


char *get_boundary(char *mfd)
{
	char *p, *end;
	char *boundary = NULL;
	int boundary_size;
	
	if ((p = strstr(mfd, "boundary=")) == NULL) {
		return NULL;
	}

	p += 9;
	if ((end = strstr(p, "\r\n")) == NULL) {
		return NULL;
	}
	
	boundary_size = end - p + 1;
	boundary = malloc(boundary_size);

	strncpy(boundary, p, boundary_size);
	boundary[boundary_size - 1] = 0;
	
	return boundary;
}


char* mutipart_form_data(char *mfd, char *boundary, char **name, char **content)
{
	char *p, *end;
	int size;
	int boundary_size;

	*content = *name = NULL;
	if ( (p = strstr(mfd, "name=")) == NULL) {
		return -1;
	}
	p += 6;
	if ((end = strchr(p, '\"')) == NULL) {
		return -1;
	}

	// 获取name
	size = end - p + 1;
	*name = malloc(size);
	strncpy(*name, p, size);
	(*name)[size - 1] = 0;
	
	// 获取内容
	p = end + 1;
	if ((end = strstr(p, boundary)) == NULL) {
		free(*name);
		*name = NULL;
		return -1;
	}

	boundary_size = strlen(boundary);
	mfd = end + boundary_size;

	while(*p == '\r' || *p == '\n') {
		p++;
	}
	
	end -= 3;
	while(*end == '\r' || *end == '\n') {
		end--;
	}

	if (p > end) {
		free(*name);
		*name = NULL;
		return -1;
	}

	size = end - p + 2;
	*content = malloc(size);
	strncpy(*content, p, size);
	(*content)[size - 1] = 0;
	
	if (*(mfd + 1) == '-') {
		// 说明到了最后了
		return NULL;
	}

	return mfd;
}


int main(int argc, char *argv[])
{
	FILE *fp;
	char *f_buf;
	char *boundary;
	size_t f_size;
	fp = fopen(argv[1], "r");

	struct stat f_stat;
	stat(argv[1], &f_stat);
	f_size = f_stat.st_size;
	if (f_size <= 0) {
		printf("fail!!!!!!!\n");
		return 0;
	}
	
	f_buf = malloc(f_stat.st_size + 1);

	fread(f_buf, f_size, 1, fp);
	char *mfd = f_buf;

	
	boundary = get_boundary(f_buf);
	printf("boundary=%s\n", boundary);
	
	while (1) {
		char *name, *content;
		mfd = mutipart_form_data(mfd, boundary, &name, &content);
		if (mfd == -1) {
			break;
		}
                // show 
		printf("name=\"%s\" content=\"%s\"\n", name, content);
		free(name);
		free(content);
		if (mfd == NULL) {
			break;
		}
	}
	
	return 0;
}



### 正确配置和使用 HTTP 请求中的 `Content-Type: multipart/form-data` `Content-Type: multipart/form-data` 是一种常见的 HTTP 编码方式,主要用于上传文件以及传递复杂表单数据。以下是关于其正确配置和使用的详细介绍: #### 1. **基本概念** `multipart/form-data` 将请求体分为多个部分(part),每一部分可以是一个简单的键值对或者一个文件流。这种类型的请求通常由客户端发起,并通过特定的边界字符串(boundary)来区分不同的部分[^1]。 #### 2. **请求结构** 当发送 `multipart/form-data` 类型的请求时,请求头部会包含如下内容: ```http POST /upload HTTP/1.1 Host: example.com Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW ``` 其中,`boundary` 参数定义了每部分内容之间的分隔符。实际的数据会被分割成多段,每一段都以该边界字符串作为起始标志[^3]。 #### 3. **实现细节** ##### (1) 文件与参数混合传输 如果需要同时上传文件并附带其他参数,则可以在同一个请求中组合这些信息。例如,在 Python 中可以通过以下方法构建这样的请求: ```python import requests url = 'https://example.com/upload' files = { 'file': ('test.txt', open('path/to/test.txt', 'rb')), } data = { 'username': 'john_doe', 'password': 'secure_password', } response = requests.post(url, files=files, data=data) print(response.text) ``` 上述代码片段展示了如何利用 `requests` 库创建带有文件和其他字段的 `multipart/form-data` 请求[^2]。 ##### (2) 避免常见错误 - 不要在 Headers 手动指定 `Content-Type: application/json` 或者类似的不匹配类型,这会导致服务器无法解析传入的内容。 - 确保所选工具(如 Postman 或 cURL)能够自动生成合适的边界字符串,而不是手动干预除非必要情况。 #### 4. **调试技巧** 为了验证请求是否按预期工作,开发者可借助浏览器开发者工具查看网络流量详情,确认提交的数据格式无误。另外也可以启用服务端日志记录功能观察接收到的具体数据形式。 ---
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值