如何用CGI C实现同时上传多个文件?
dglwx
|
1#
dglwx 发表于 2008-03-05 16:29
如何用CGI C实现同时上传多个文件?
好不容易在google里搜到一个没用CGIC库的上传文件的CGI C代码,工作得怪happy的,只是不能同时上传多个文件.不敢专功,留下来给需要的人!对CGI不熟,请问如何才能实现用CCI C同时上传多个文件?
[Copy to clipboard] [ - ]
CODE:
#include <stdio.h>
#include <stdlib.h> #include <string.h> #include <sys/stat.h> #include <time.h> #include <fcntl.h> //want to check file extensions? 1=yes 0=no #define CHECKEXT 1 //define max size of uploads to 100k #define MAXSIZE 2000000 //define upload directory relative to cgi-bin #define UPLOADIR "/tmp/upload" // buffer for storing boundary line and file name #define MAXLINE 512 char szBoundary[MAXLINE]; char szFile[MAXLINE]; //filename to write to char myFile[MAXLINE]; //basename of uploaded file //buffer of arbitrary size for reading from STDIN #define BUFFSIZE 16*1024 char szBuff[BUFFSIZE]; /************************************************** ************************* * For file upload, CGI variables look like this: * CONTENT_TYPE=multipart/form-data; boundary=----- ----------------------14422580032340 CONTENT_LENGTH=216 STDIN contains the following information: -----------------------------14422580032340 Content-Disposition: form-data; name="file"; filename="/home/user/myup.jpg" Content-Type: text/plain Data from file goes here---- -------------------------14422580032340 *************************************************************************/ /*sub routine to test extensions it only allows 1 dot in name, ie myup.1.jpg * is not allowed but myup-1.tar.gz is OK because tar.gz is a defined extension*/ int getext(const char *filename) { char *p, *q; int len,i,isgood = 0; char *goodext[9] = {"gif","jpg","jpeg","png","bmp","tgz","gz","txt","tar.gz"}; char ext[7]; //6 chars plus '\0' /*move to first dot */ if (!(p = strchr(filename, '.'))) return 0; /* move past the dot */ ++p; /*move to end of string */ if (!(q = strchr(p, '\0'))) return 0; len = q - p; memcpy(ext, p, len); ext[len] = '\0'; for (i=0;i<=9;i++) { if(strcmp(ext,goodext[i]) == 0) { isgood = 1; } } return isgood; } ///////////////////////////////////////////////////////////// int main(int argc, char **argv[]) { int rc = 0; char *up= UPLOADIR; char *psz1; char *psz2; FILE *out = NULL; long i, total, count; char *ContentLength; /* Pointer to CONTENT_LENGTH environment variable. */ long InCount; /* The supposed number of incoming bytes. */ char *filename; printf("Content-type: text/html\n\n"); printf("<html>"); printf("<head><title>File Upload</title></head>\n"); printf("<center><h1>File Upload Status</h1></center>\n"); ContentLength = getenv("CONTENT_LENGTH"); InCount = atol(ContentLength); if (InCount > MAXSIZE) { rc=7; goto Error; } // null out file name buffer memset(szFile, 0, sizeof(szFile)); // first line should be MIME boundary, prepend cr/lf szBoundary[0] = '\r'; szBoundary[1] = '\n'; szBoundary[2] = '\0'; if (fgets(&szBoundary[2], sizeof(szBoundary)-2, stdin) == NULL) { rc = 1; goto Error; } //strip terminating CR / LF if ((psz1=strchr(&szBoundary[2],'\r')) != NULL) { *psz1 = '\0'; } if ((psz1=strchr(&szBoundary[2],'\n')) != NULL) { *psz1 = '\0'; } // second line should contain "Content-Disposition: if (fgets(szBuff, sizeof(szBuff), stdin) == NULL) { rc = 2; goto Error; } // get filename keyword if ((psz1=strstr(szBuff, "filename=")) == NULL) { rc = 3; goto Error; } // get pointer to actual filename (it's in quotes) psz1+=strlen("filename="); if ((psz1 = strtok(psz1, " \"")) == NULL) { rc = 4; goto Error; } // remove leading path for both PC and UNIX systems if ((psz2 = strrchr(psz1,'\\')) != NULL) { psz1 = psz2+1; } if ((psz2 = strrchr(psz1,'/')) != NULL) { psz1 = psz2+1; } //psz1 now points to a file name, try to create it in our system sprintf(szFile, "%s/%s",up,psz1); //file to actually write sprintf(myFile, "%s", psz1); //basename of file filename= myFile; //check for valid extension if (CHECKEXT) { if ((getext(filename))== 0) { rc = 8; goto Error; } } // determine if file exists, and don't allow overwritting if ((out = fopen(szFile, "rb")) != NULL) // file already exists! { rc = 5; goto Error; } if ((out = fopen(szFile, "wb+")) == NULL) { rc = 6; goto Error; } // throw away until we get a blank line while (fgets(szBuff, sizeof(szBuff), stdin) != NULL) { if (strlen(szBuff) <= 2) { break; } } // copy the file while ((count=fread(szBuff, 1, sizeof(szBuff), stdin)) != 0) { if ((i=fwrite(szBuff, 1, count, out)) != count) { rc = 7; goto Error; } //disk write error } // re read last 128 bytes of file, handling files < 128 bytes if ((count = ftell(out)) == -1) { rc = 8; goto Error; } if (count > 128) { count = 128; } if (fseek(out, 0-count, SEEK_END) != 0) { rc = 9; goto Error; } // get the new position if ((total = ftell(out)) == -1) { rc = 10; goto Error; } // and read the data count = fread(szBuff, 1, sizeof(szBuff), out); szBuff[count] = '\0'; // determine offset of terminating boundary line rc = 11; for (i=0; i<=(count-(long)strlen(szBoundary)); i++) { if ((szBuff[i] == szBoundary[0]) && (strncmp(szBoundary, &szBuff[i], strlen(szBoundary)) == 0)) { total+=i; rc = 0; break; } } // if rc is still set, we didn't find the terminating boundary line if (rc != 0) { goto Error; } if (total == 0) { rc = 11; goto Error; } // truncate the file at the correct length by writing 0 bytes fflush(out); Error: if (out != NULL) { fclose(out); } switch (rc) { case 0: // success printf("The file <b> %s %d bytes</b> was uploaded sucessfully.",myFile,InCount); break; case 5: // file exists printf ("The file %s already exists and cannot be overwritten.Please try again with a different file.\n", myFile); break; case 7: // file too big printf ("The file <b> %s </b> is too big. Try again.",myFile); break; case 8: // file is not an allowed type printf ("The file <b> %s </b> is not an allowed type. Try again.",myFile); break; case 11: // 0 byte file printf("The file <b>%s </b>contains no data.<br>Please try again with a different file.", myFile); unlink(szFile); break; default: // all other cases printf("Error %d uploading file<b>%s </b>Please try again.", rc, myFile); unlink(szFile); break; } if ((psz1=getenv("HTTP_REFERER")) != NULL) { printf("<p><A HREF =\"%s\">Back</A>", psz1); } printf("</html>\n"); return 0; } |