CGI的后端,简单理解就是C、或者python写的后端服务,接收前端HTML form表单的输入,然后进行相应的操作。
CGI上传程序花的时间相对多些,在deepseek生成代码的基础上,结合抓包对form表单的分析,确实效率是提升了不少。但deepseek不能解决所有的问题,就跟网上说的一样,碰到程序员的问题,给出的答案就开始胡说,哈哈哈。



其中上传程序的CGI代码参考:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <signal.h>
#include <fcntl.h>
#define UPLOAD_DIR "/tmp/bms/" // 上传文件保存目录
#define BUF_SIZE 4096
// 创建上传目录(如果不存在)
void create_upload_dir() {
if (access(UPLOAD_DIR, F_OK)) {
mkdir(UPLOAD_DIR, 0777);
}
}
// 安全释放指针并将指针置空
#define SAFE_FREE(ptr) do { free(ptr); (ptr) = NULL; } while (0)
/*
* 在内存中找出一段字符串,返回出现的首地址
* m 缓冲区地址
* len 缓冲区长度
* str 带有结束符的字符串
*/
void *memstr(unsigned char *m, int len, const char *str)
{
unsigned char *sub = (unsigned char *)str;
unsigned char *s, *d;
int i = 0;
int slen = len - strlen(str) + 1;
if ((m == NULL) || (slen < 1)) {
return NULL;
}
while (i < slen) {
s = m + i; d = (unsigned char *)str;
while(*s == *d) {
s += 1;
d += 1;
};
if (*d == 0) {
return m + i;
}
i += 1;
}
return NULL;
}
// 解析 multipart/form-data 数据
void parse_multipart_data(const char *boundary) {
char *line = NULL;
size_t line_len = 0;
FILE *file = NULL;
char filepath[256];
char buffer[BUF_SIZE];
int start_flag = 0;
struct timeval tv;
gettimeofday(&tv, NULL);
int curr_system_time = tv.tv_sec*1000+tv.tv_usec/1000;//ms
// 逐行读取输入
while (1) {
getline(&line, &line_len, stdin);
// 1. 查找文件名
if (!file && strstr(line, "filename=\"")) {
char *filename_start = strstr(line, "filename=\"") + 10;
char *filename_end = strchr(filename_start, '\"');
if (!filename_end) continue; // 格式错误
*filename_end = '\0'; // 截断文件名
//snprintf(filepath, sizeof(filepath), "%s/%d_%s.tar.gz", UPLOAD_DIR, curr_system_time, filename_end);
snprintf(filepath, sizeof(filepath), "%s/%s", UPLOAD_DIR, filename_start);
sprintf(buffer, "rm %s -rf", filepath);
system(buffer);
// 打开文件
if (!(file = fopen(filepath, "wb"))) {
printf("Status: 500\r\nContent-Type: application/json\r\n\r\n"
"{\"code\":1, \"msg\":\"Failed to open file\"}");
SAFE_FREE(line);
return;
}
// 跳过头部剩余部分直到空行
while (getline(&line, &line_len, stdin) != -1 && strcmp(line, "\r\n") != 0) {
free(line);
line = NULL;
}
SAFE_FREE(line);
break;
}
SAFE_FREE(line);
}
int file_len=atoi(getenv("CONTENT_LENGTH"));
char *http_buf=(char *)malloc(file_len+1);
if (http_buf == NULL) {
printf("malloc fail.\r\n");
return;
}
memset((char *)http_buf,0x0,file_len+1);
char *tmp = http_buf;
int readlen = 0;
int ret = 0;
int temp_len = file_len;
int read_count = 0;
while (temp_len) {
readlen = (temp_len > 1024) ? 1024 : temp_len;
ret =fread(tmp, 1, readlen, stdin);
if(readlen != ret) {
read_count += ret;
//printf("failed to read len %d size %d\r\n", readlen, ret);
break;
}
read_count += ret;
tmp += readlen;
temp_len -= readlen;
}
tmp = http_buf;
#if 1
read_count -= 2 + strlen(boundary) + 2;
fwrite(tmp, 1, read_count, file);
#else
if (tmp[0] = '\n'){
tmp += 1;
read_count -= 1;
}else if (tmp[0] = '\r' && tmp[1] == '\n'){
tmp += 2;
read_count -= 2;
}
char *end = memstr(tmp, read_count , boundary);
if (end == NULL){
fwrite(tmp, 1, read_count, file);
}else{
read_count = end - tmp + 1;
fwrite(tmp, 1, read_count, file);
}
#endif
printf("Status: 200 OK\r\n");
printf("Content-Type: application/json\r\n\r\n");
printf("{\"code\": 0, \"boundary\":\"%s\", \"msg\": \"File uploaded successfully\"}", boundary);
free(http_buf);
// 清理残留
if (file) fclose(file);
SAFE_FREE(line);
}
int main() {
// 创建上传目录
create_upload_dir();
// 获取 Content-Type 中的 boundary
char *content_type = getenv("CONTENT_TYPE");
if (!content_type || !strstr(content_type, "multipart/form-data")) {
printf("Status: 400 Bad Request\r\n");
printf("Content-Type: application/json\r\n\r\n");
printf("{\"code\": 1, \"msg\": \"Invalid content type ,%s\"}", content_type);
return 1;
}
char *boundary_start = strstr(content_type, "boundary=");
if (!boundary_start) {
printf("Status: 400 Bad Request\r\n");
printf("Content-Type: application/json\r\n\r\n");
printf("{\"code\": 1, \"msg\": \"No boundary found\"}");
return 1;
}
boundary_start += 9; // 跳过 "boundary="
char boundary[1024];
snprintf(boundary, sizeof(boundary), "--%s--", boundary_start);
// 解析上传数据
parse_multipart_data(boundary);
return 0;
}deepseek给的几个版本,上传的文件,写出来的内容总是差很多个字节。细节处理包括:
1、回车符号的处理;
2、分隔符的处理,特别是分隔符号的长度处理,--%s--,这也是调试才能发现的问题。
3、读数据到缓冲区,然后一次性写入文件内容的处理。
-------------------广告线---------------
项目、合作,欢迎勾搭,邮箱:promall@qq.com
本文为呱牛笔记原创文章,转载无需和我联系,但请注明来自呱牛笔记 ,it3q.com
