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