背景:现在很少有用C实现文件上传了,有Nginx的上传模块,用CGI实现文件上传在这里作下备案。 后加参考:http://hi.baidu.com/davidgabriel/item/58fec40b4c2f49803c42e290 用C语言库(CGIC)编写CGI,实现文件上传: http://hi.baidu.com/rszlatkfoxbalqd/item/62bb3a4e04e89c0fc0161326 使用C语言的CGI库“CGIC”完成Web开发的各种要求 : http://blog.sina.com.cn/s/blog_75a8cfac0100p9es.html add Time:2014-01-14
upload.html
- <HTML>
- <HEAD>
- <TITLE>上传数据文件</TITLE>
- <META HTTP-EQUIV="CONTENT-TYPE" CONTENT="TEXT/HTML;CHARSER=UTF-8">
- <link rel="stylesheet" type="text/css" href="css/main.css">
- <script type="text/javascript">
- function upload_file(){
- if( document.getElementById('FILE1').value == '' ){
- alert("请选择文件!");
- return false;
- }
-
- document.getElementById('uploadInfo').innerHTML = '' ;
- document.getElementById('uploadInfo').innerHTML = '<img src="images/wait.gif"><br>数据上传中,请稍候……' ;
-
- document.getElementById('form1').submit();
- }
- </script>
- </HEAD>
- <BODY BGCOLOR="#FFFFFF">
- <FORM METHOD="POST" id="form1" name="form1" ENCTYPE="multipart/form-data" ACTION="cgi-bin/uploadcgi.cgi">
- 选择文件:<INPUT TYPE="FILE" NAME="FILE1" id="FILE1" class="btn"><INPUT TYPE="button" onclick="upload_file()" VALUE="上传" class="btn"><br>
- <center>
- <div id="uploadInfo"></div>
- </center>
- </FORM>
- </BODY>
- </HTML>
############################# uploadcgi.c
- /**************************************************************************
- 2007-1-5 11:42 establish by lzh.A cgi program.
- get a file from user's explorer.
- ***************************************************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- #define DEAL_BUF_LEN 1024
- #define SIGN_CODE_LEN 100
- #define FILE_NAME_LEN 64
- #define FILE_SAVE_DIR "/var/landog/db_upload/"
-
- enum
- {
- STATE_START,
- STATE_GET_SIGN_CODE,
- STATE_GET_FILE_NAME,
- STATE_GET_FILE_START,
- STATE_GET_FILE_CONTENT,
- STATE_CHECK_END,
- STATE_END
- };
- /***************************************************************************
- ShowErrorInfo
- ****************************************************************************/
- static void ShowErrorInfo(char * error)
- {
-
- printf("Content-Type:text/html;charset=UTF-8\n\n");
- printf("<center><font color='red'>%s</font></center>" , error );
- }
-
- /* 主体从这里开始 */
-
- int main(void)
- {
- FILE *fp; /* 文件指针,保存我们要获得的文件 */
- int getState = STATE_START;
- int contentLength;/*标准输入内容长度*/
- int nowReadLen;
- int signCodeLen;
- int tmpLen;
- char *nowReadP;
- char *nowWriteP;
- char dealBuf[DEAL_BUF_LEN];
- char signCode[SIGN_CODE_LEN]; /*存储本次的特征码*/
- char tmpSignCode[SIGN_CODE_LEN];
- char fileName[FILE_NAME_LEN];
- memset(dealBuf,0,DEAL_BUF_LEN);
- memset(signCode,0,SIGN_CODE_LEN);
- memset(fileName,0,FILE_NAME_LEN);
- nowReadLen = 0;
- if((char *)getenv("CONTENT_LENGTH")!=NULL)
- {
- contentLength = atoi((char *)getenv("CONTENT_LENGTH"));
- }
- else
- {
- ShowErrorInfo("没有恢复数据!");
- exit(1);
- }
-
- while(contentLength > 0)
- {
- if(contentLength >= DEAL_BUF_LEN)
- {
- nowReadLen = DEAL_BUF_LEN;
- }
- else
- {
- nowReadLen = contentLength;
- }
- contentLength -= nowReadLen;
- if(fread(dealBuf,sizeof(char),nowReadLen,stdin) != nowReadLen)
- {
- ShowErrorInfo("读取恢复数据失败,请重试!");
- exit(1);
- }
- nowReadP = dealBuf;
- while(nowReadLen > 0)
- {
- switch (getState)
- {
- case STATE_START:
- nowWriteP = signCode;
- getState = STATE_GET_SIGN_CODE;
- case STATE_GET_SIGN_CODE:
- if(strncmp(nowReadP,"\r\n",2) == 0)
- {
- signCodeLen = nowWriteP - signCode;
- nowReadP++;
- nowReadLen--;
- *nowWriteP = 0;
- getState = STATE_GET_FILE_NAME;
- //ShowErrorInfo(signCode);
- }
- else
- {
- *nowWriteP = *nowReadP;
- nowWriteP++;
- }
- break;
- case STATE_GET_FILE_NAME:
- if(strncmp(nowReadP,"filename=",strlen("filename=")) == 0)
- {
- nowReadP += strlen("filename=");
- nowReadLen -= strlen("filename=");
- nowWriteP = fileName + strlen(FILE_SAVE_DIR);
- while(*nowReadP != '\r')
- {
- if(*nowReadP == '\\' || *nowReadP == '/')
- {
- nowWriteP = fileName + strlen(FILE_SAVE_DIR);
- }
- else if(*nowReadP != '\"')
- {
- *nowWriteP = *nowReadP;
- nowWriteP++;
- }
- nowReadP++;
- nowReadLen--;
- }
- *nowWriteP = 0;
- nowReadP++;
- nowReadLen--;
- getState = STATE_GET_FILE_START;
- memcpy(fileName,FILE_SAVE_DIR,strlen(FILE_SAVE_DIR));
- if((fp=fopen(fileName,"w"))==NULL)
- {
- fprintf(stderr,"open file error\n");
- exit(1);
- }
- //ShowErrorInfo(fileName);
- }
- break;
- case STATE_GET_FILE_START:
- if(strncmp(nowReadP,"\r\n\r\n",4) == 0)
- {
- nowReadP += 3;
- nowReadLen -= 3;
- getState = STATE_GET_FILE_CONTENT;
- //ShowErrorInfo("get");
- }
- break;
- case STATE_GET_FILE_CONTENT:
- if(*nowReadP != '\r')
- {
- fputc(*nowReadP,fp);
- }
- else
- {
- if(nowReadLen >= (signCodeLen + 2))
- {
- if(strncmp(nowReadP + 2,signCode,signCodeLen) == 0)
- {
- getState = STATE_END;
- nowReadLen = 1;
- ShowErrorInfo("数据上传成功");
- /* if( system( "/var/landog/app/sniff/db_recover.sh" ) == 0 ){
- ShowErrorInfo( "数据库恢复完成,请重新启动landog" );
- }else{
- ShowErrorInfo( "数据库恢复过程中出现错误,错误原因:恢复的文件已经损坏" );
- }
- */
- }
- else
- {
- fputc(*nowReadP,fp);
- }
- }
- else
- {
- getState = STATE_CHECK_END;
- nowWriteP = tmpSignCode;
- *nowWriteP = *nowReadP;
- nowWriteP++;
- tmpLen = 1;
- }
- }
- break;
- case STATE_CHECK_END:
- if(*nowReadP != '\r')
- {
- if(tmpLen < signCodeLen + 2)
- {
- *nowWriteP = *nowReadP;
- nowWriteP++;
- tmpLen++;
- if(tmpLen == signCodeLen + 2)
- {
- *nowWriteP = 0;
- if((tmpSignCode[1] == '\n')&&(strncmp(tmpSignCode + 2,signCode,signCodeLen) == 0))
- {
- getState = STATE_END;
- nowReadLen = 1;
- ShowErrorInfo("数据上传成功");
- /* if( system( "/var/landog/app/sniff/db_recover.sh" ) == 0 ){
- ShowErrorInfo( "数据库恢复完成,请重新启动landog" );
- }else{
- ShowErrorInfo( "数据库恢复过程中出现错误,错误原因:恢复的文件已经损坏" );
- }
- */
- }
- else
- {
- //fprintf(fp,tmpSignCode);
- fwrite(tmpSignCode,sizeof(char),tmpLen,fp);
- getState = STATE_GET_FILE_CONTENT;
- }
- }
- }
- }
- else
- {
- *nowWriteP = 0;
- //fprintf(fp,tmpSignCode);
- fwrite(tmpSignCode,sizeof(char),tmpLen,fp);
- nowWriteP = tmpSignCode;
- *nowWriteP = *nowReadP;
- nowWriteP++;
- tmpLen = 1;
- }
- break;
- case STATE_END:
- nowReadLen = 1;
- break;
- default:break;
- }
- nowReadLen--;
- nowReadP++;
- }
- }
- if(fp != NULL)
- {
- fclose(fp);
- }
- return 0;
- }
========================================================================= 另一个写在一个文件里的CGI文件上传方式,[备注:]C语言-cgi文件上传代码,它通过 getenv("CONTENT_LENGTH") 之后可以直接对stdin使用fread() 但是在实际应用时发现,有时候文件读不全 ,注意要使用二进制模式来读取,而不是文本模式:
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <fcntl.h>
- #define ACHEAD "ooooooooooooo"
- #define AC483PATH "../htdocs/ac483/ac483_bak"
- void fit(char *,unsigned size);
-
- int main(int argc, char *argv[])
- {
- printf("Content-Type:text/html\n\n");
- char *pMethod = getenv("REQUEST_METHOD");
- //printf("pMethod=%s\n",pMethod);
- if(pMethod == NULL || *pMethod == 0)
- {
- printf("No Any Method!\n");
- return 0;
- }
-
- if(strcmp(pMethod, "GET") == 0)
- return 1;
-
- if(strcmp(pMethod, "POST") == 0)
- {
- char *pCntLen = getenv("CONTENT_LENGTH");
- //printf("pCntLen=%s\n",pCntLen);
- if(!pCntLen)
- {
- printf("Can't get Content_Length!\n");
- return 0;
- }
- if(*pCntLen == 0)
- {
- printf("Can't get Content_Length!\n");
- return 0;
- }
- int StrLen = atoi(pCntLen);
- // printf("StrLen=%d\n",StrLen);
- if(StrLen <= 0)
- {
- printf("String Length <= 0\n");
- return 0;
- }
- //char *ph = getenv("CONTENT_TYPE");
- //printf("ph=%s\n",ph);
-
- char *readstr=(char *)malloc(StrLen+1);
- fread(readstr,StrLen,1,stdin);
- // printf("readstr=%s\n",readstr);
- int n=0;
- int firstLineMark=0;
- int firstLineCount=0;
- int headCount=0;
- while(n<4)
- {
- if(*(readstr++)=='\n')
- {
- firstLineMark++;
- n++;
- }
- if(firstLineMark==0)
- {
- firstLineCount++;
- }
- headCount++;
-
- }
-
- StrLen = StrLen-headCount;
- fit(readstr,13);
- if(strcmp(readstr,ACHEAD)!=0)
- {
- printf("<SCRIPT language=JavaScript>alert('文件不正确!');javascript:history.go(-1)</SCRIPT>");
-
- return 0;
- }
- FILE *fp;
- if((fp=fopen(AC483PATH,"wb"))==NULL)
- {
- printf("error open file\n");
- return 0;
- }
- fwrite(readstr+13,StrLen-13-firstLineCount-5,1,fp);
- fclose(fp);
- printf("<SCRIPT language=JavaScript>alert('恭喜升级成功!');javascript:history.go(-1)</SCRIPT>");
- // printf("恭喜升级成功!");
-
-
- }
- return 0;
- }
- void fit(char *string,unsigned size)
- {
- if(strlen(string)>size)
- *(string+size)='\0';
- }
打开一个文件,上传到服务器指定的文件中.适用于一些软件在线更新.文字! CGI中文件无法上传 在调试cgictest.cgi过程中,发现文件无法上传,提示“No file was uploaded.”。 原因有两点: 1、boa的用户权限不够,无法建立临时文件。改为root用户启动 2、cgi是以GET形式发送表格的。改为POST形式。
更多参考: http://hi.baidu.com/andforce/item/787a822953d87bc9dcf69ac3 http://wenku.baidu.com/view/35fc800b52ea551810a687ed.html http://blog.csdn.net/xyj0663/article/details/4666146作者:justwinit@向东博客 专注WEB应用 构架之美 --- 构架之美,在于尽态极妍 | 应用之美,在于药到病除 地址:http:///post/6314/ 版权所有。转载时必须以链接形式注明作者和原始出处及本声明!
|