windows C++ HTTP服务器文件下载器与Ajax上传问题

owfi6suc  于 6个月前  发布在  Windows
关注(0)|答案(1)|浏览(82)

出于某些原因和教育目的,我从头开始开发了一个C++ HTTP服务器,它应该用AJAX处理动态请求从HTML页面捕获文件上传,并将其保存在服务器程序所在的同一目录中。
服务器工作正常.txt文件.文件上传并保存在服务器目录中没有任何缺陷.一切都保持完美,但问题开始时,我试图上传二进制文件,如,可执行文件,视频文件,音乐文件和其他.基本上,服务器工作正常.txt文件不与其他.每当上传二进制文件,服务器端的输出文件以某种方式被损坏。
我知道有PHP和NodeJS框架可以实现这些操作,但实际上我将在一个裸金属控制器服务器上部署这个项目,该服务器的资源非常有限,无法承受复杂的框架。所以使用scratch的C服务器似乎是实现我目标的唯一方法。虽然我不能直接将此代码移植到控制器中,程序保持不变。2为了直接了解程序,我必须使用Windows套接字在Windows上进行一些实验。
这是我迄今为止所尝试的,
C
HTTP服务器代码。

#include <stdio.h>
#include <math.h>
#include <cmath>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <winsock2.h>
#include <windows.h>

#define PORT 12345

WSADATA ws;

char Command[8888];

char FILEDATA[(2 * 1024)];  // FILE HEADER and BUFFER
SOCKET soc, acpt;
FILE *f ;



unsigned long long FileSize(char * direc){
    
    unsigned long long size = 0;
    
    FILE *fsize = fopen(direc,"rb");
    
    fseek(fsize,0,SEEK_END);
    size = _ftelli64(fsize);
    fseek(fsize,0,SEEK_SET);
    
    fclose(fsize);
    
    return size;
    
}
        

void Serve(){
    
    
    int optval = 1;
    int RecvBytes=0;
    
    sockaddr_in addr, peerAddr;
    struct timeval RequestTimeout = {0,5000000} , DownloadTimeout= {0,500000};
    char URL[4000]={0};
    char FileName[260]={0};
    
    
    addr.sin_addr.s_addr = inet_addr("0.0.0.0");
    addr.sin_family = AF_INET;
    addr.sin_port = htons(PORT);
    
    fd_set rfd;
    FD_ZERO(&rfd);
    
    
    soc = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    setsockopt(soc,SOL_SOCKET,SO_REUSEADDR,(const char*)&optval,sizeof(optval));
    
    bind(soc,(sockaddr*)&addr,sizeof(addr));
    listen(soc,100);
    
    
    
    
    acpt = accept(soc,NULL,NULL);
    
    FD_SET(acpt,&rfd);
    
    int connstat = select(acpt+1,&rfd,NULL,NULL,&RequestTimeout); // act only if a stable reading can be performed
    
    if(connstat){
    
        int x = 0;
        RecvBytes = recv(acpt,Command,sizeof(Command),0);     // Receives HTTP header
    
        RecvBytes = recv(acpt,FILEDATA,sizeof(FILEDATA),0);     // Receives File headers and content
        
        char * namePtr = strstr(FILEDATA,"\r\n\r\n");
        namePtr = strstr(FILEDATA,"filename=\"") + strlen("filename  "); // Extraction of File Name begins here
        
        while(namePtr[x]!='"'){
            x++;
        }
        
        strncpy(FileName,namePtr,x);              // Extraction of file name ends here.
        
        printf("NAME: %s\n\n",FileName);
        
        int NumberOfBytes = (&strstr(FILEDATA,"\r\n\r\n")[0]+2 - &FILEDATA[0])+2;
        
        f = fopen(FileName,"wb");             // Open file for writing
        
        
        fwrite(strstr(FILEDATA,"\r\n\r\n")+3,1,RecvBytes - NumberOfBytes ,f);   // Received Number of Bytes - Number of Bytes Till Header
        
        
        while(select(acpt+1,&rfd,NULL,NULL,&DownloadTimeout)){    // Keep reading if more data remains available
            RecvBytes = recv(acpt,FILEDATA,sizeof(FILEDATA),0);   // receive
            if(RecvBytes==0){                                     
                break;
            }
            fwrite(FILEDATA,1,RecvBytes,f);
        }
        
    }
    
    
    
    fclose(f);
    
    
    unsigned long long truncFile = FileSize(FileName) - 45;
    
    f = fopen(FileName,"r+");                     // truncating file to remove the webkit boundary substring at the end of the file.
    ftruncate(fileno(f),truncFile);
    fclose(f);
    
    printf("OUTPUT FILE SIZE: %llu\n\n",FileSize(FileName));
    
    MessageBeep(MB_ICONERROR); // A beep means operation is complete
    
    
    shutdown(acpt,2);
    closesocket(acpt);
    
    closesocket(soc);
    shutdown(soc,2);
    
    acpt = NULL;
    soc = NULL;
    
    memset(FILEDATA,'\0',sizeof(FILEDATA));
    
}
        

int main(){
    
    //printf("%d\n",strlen("------WebKitFormBoundary5BlPHcjSKYuZFzV3--")); 42
    
    WSAStartup(MAKEWORD(2,2),&ws);
    
    while(1){
        Serve();
    }
    
    
    return 0;
}

字符串
现在用于上传的AJAX HTML页面,

<!DOCTYPE html>
<html>

<body>
The content of the body element is displayed in your browser.

<input type="file" id="image-file">
<button onclick="Send()">Send</button>

<script>

function Send(){
    
    let photo = document.getElementById("image-file").files[0];  // file from input
    let req = new XMLHttpRequest();
    let formData = new FormData();

    formData.append("photo", photo);                            
    req.open("POST", 'http://localhost:12345/');
    req.send(formData);
    
}

</script>

</body>

</html>


我想有一个最快的解决这个问题的办法。谢谢你理解我的关心,问候…

9rbhqvlz

9rbhqvlz1#

最后,经过大量的斗争,这些代码做完美的工作!
C HTTP服务器下载器

#include <stdio.h>
#include <math.h>
#include <cmath>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <winsock2.h>
#include <windows.h>

#define PORT 12345

WSADATA ws;

char Command[8888];

char FILEDATA[(16 * 1024 * 1024)];  // FILE HEADER and BUFFER
SOCKET soc, acpt;
FILE *f ;



unsigned long long FileSize(char * direc){
    
    unsigned long long size = 0;
    
    FILE *fsize = fopen(direc,"rb");
    
    fseek(fsize,0,SEEK_END);
    size = _ftelli64(fsize);
    fseek(fsize,0,SEEK_SET);
    
    fclose(fsize);
    
    return size;
    
}
        

void Serve(){
    
    
    int optval = 1;
    int RecvBytes=0;
    
    sockaddr_in addr, peerAddr;
    struct timeval RequestTimeout = {0,5000000} , DownloadTimeout= {0,500000};
    char URL[4000]={0};
    char FileName[260]={0};
    
    
    addr.sin_addr.s_addr = inet_addr("0.0.0.0");
    addr.sin_family = AF_INET;
    addr.sin_port = htons(PORT);
    
    fd_set rfd;
    FD_ZERO(&rfd);
    
    
    soc = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    setsockopt(soc,SOL_SOCKET,SO_REUSEADDR,(const char*)&optval,sizeof(optval));
    
    bind(soc,(sockaddr*)&addr,sizeof(addr));
    listen(soc,100);
    
    
    
    
    acpt = accept(soc,NULL,NULL);
    
    FD_SET(acpt,&rfd);
    
    int connstat = select(acpt+1,&rfd,NULL,NULL,&RequestTimeout);
    
    if(connstat){
    
        int x = 0;
        RecvBytes = recv(acpt,Command,sizeof(Command),0);     // Receives HTTP header
    
        RecvBytes = recv(acpt,FILEDATA,sizeof(FILEDATA),0);     // Receives File headers and content
        
        char * namePtr = strstr(FILEDATA,"\r\n\r\n");
        namePtr = strstr(FILEDATA,"filename=\"") + strlen("filename  "); // Extraction of File Name begins here
        
        while(namePtr[x]!='"'){
            x++;
        }
        
        strncpy(FileName,namePtr,x);              // Extraction of file name ends here.
        
        printf("NAME: %s\n\n",FileName);
        
        int NumberOfBytes = (&strstr(FILEDATA,"\r\n\r\n")[0]+2 - &FILEDATA[0])+2;
        
        f = fopen(FileName,"wb");             // Open file for writing
        
        printf("CONTENTS: %d ",  &strstr(FILEDATA,"\r\n\r\n")[0]+2 - &FILEDATA[0]);
        
        fwrite(strstr(FILEDATA,"\r\n\r\n")+4,1,RecvBytes - NumberOfBytes ,f);   // Received Number of Bytes - Number of Bytes Till Header
        
        
        while(select(acpt+1,&rfd,NULL,NULL,&DownloadTimeout)){    // Keep reading if more data remains available
            RecvBytes = recv(acpt,FILEDATA,sizeof(FILEDATA),0);   // receive
            if(RecvBytes==0){                                     
                break;
            }
            fwrite(FILEDATA,1,RecvBytes,f);
        }
        
    }
    
    
    
    fclose(f);
    
    
    unsigned long long truncFile = FileSize(FileName) - 45;
    
    f = fopen(FileName,"r+b");                     // truncating file to remove the webkit boundary
    ftruncate(fileno(f),truncFile);
    fclose(f);
    
    printf("OUTPUT FILE SIZE: %llu\n\n",FileSize(FileName));
    
    MessageBeep(MB_ICONERROR); // A beep means operation is complete
    
    
    shutdown(acpt,2);
    closesocket(acpt);
    
    closesocket(soc);
    shutdown(soc,2);
    
    acpt = NULL;
    soc = NULL;
    
    memset(FILEDATA,'\0',sizeof(FILEDATA));
    
}
        

int main(){
    
    //printf("%d\n",strlen("------WebKitFormBoundary5BlPHcjSKYuZFzV3--")); 42
    
    WSAStartup(MAKEWORD(2,2),&ws);
    
    while(1){
        Serve();
    }
    
    
    return 0;
}

字符串
HTML与AJAX插件

<!DOCTYPE html>
<html>

<body>
The content of the body element is displayed in your browser.

<input type="file" id="image-file">
<button onclick="Send()">Send</button>

<script>

function Send(){
    
    let photo = document.getElementById("image-file").files[0];  // file from input
    let req = new XMLHttpRequest();
    let formData = new FormData();

    formData.append("photo", photo);                            
    req.open("POST", 'http://localhost:12345/');
    req.send(formData);
    
}

</script>

</body>

</html>


上面的C HTTP服务器代码在保存服务器的目录中完美地处理和下载上传请求,而不会损坏文件。

相关问题