Проблема с загрузкой файлов HTTP-сервера C++ с загрузчиком Ajax [решено] ⇐ C++
Проблема с загрузкой файлов HTTP-сервера C++ с загрузчиком Ajax [решено]
По некоторым причинам и в образовательных целях я разработал с нуля HTTP-сервер C++, который должен перехватывать загрузки файлов со страницы HTML с помощью AJAX, обрабатывающего динамические запросы, и сохранять их в том же каталоге, где находится серверная программа.
>
Сервер отлично работает с файлами .txt. Файлы загружаются и сохраняются в каталоге сервера без каких-либо ошибок. Все остается идеальным, но проблема начинается, когда я пытаюсь загрузить двоичные файлы, такие как исполняемые файлы, видеофайлы, музыкальные файлы и другие. По сути, сервер работает нормально с файлами .txt, а не с другими. Всякий раз, когда загружается двоичный файл, выходной файл на стороне сервера каким-то образом повреждается.
Я знаю, что для этих операций существуют платформы PHP и NodeJS, но на самом деле я буду развертывать этот проект на чистом сервере контроллера, который имеет очень ограниченное количество ресурсов, которые не могут противостоять сложным платформам. Таким образом, сервер C++ с использованием нуля кажется единственным способом достижения моей цели. Хоть я и не могу напрямую портировать этот код в контроллер, процедура остаётся прежней. Чтобы узнать об этой процедуре из первых рук, мне придется провести несколько экспериментов в Windows с использованием Windows Sockets.
Вот что я уже пробовал
Код HTTP-сервера C++.
#include #include #include #include #include #include #include #include #define ПОРТ 12345 ВСАДАТА ws; символ Команда [8888]; char FILEDATA[(2 * 1024)]; // ЗАГОЛОВОК ФАЙЛА и БУФЕР SOCKET соц, акцепт; ФАЙЛ *f ; беззнаковый длинный длинный FileSize(char * direc){ беззнаковый длинный длинный размер = 0; ФАЙЛ *fsize = fopen(direc,"rb"); fseek(fsize,0,SEEK_END); размер = _ftelli64 (fsize); fseek(fsize,0,SEEK_SET); fзакрыть (размер); размер возврата; } недействительный Служить () { интервал optval = 1; интервал RecvBytes = 0; sockaddr_in адрес, адрес узла; struct timeval RequestTimeout = {0,5000000}, DownloadTimeout = {0,500000}; символьный 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(ПОРТ); fd_set РФД; FD_ZERO(&rfd); soc = сокет (AF_INET, SOCK_STREAM, IPPROTO_TCP); setockopt(soc,SOL_SOCKET,SO_REUSEADDR,(const char*)&optval,sizeof(optval)); связывание(soc,(sockaddr*)&addr,sizeof(addr)); слушать (соц, 100); акпт = принять (сок, NULL, NULL); FD_SET(принять,&rfd); int connstat = select(acpt+1,&rfd,NULL,NULL,&RequestTimeout); // действуем только в том случае, если можно выполнить стабильное чтение если (connstat) { интервал х = 0; RecvBytes = Recv(acpt,Command,sizeof(Command),0); // Получает HTTP-заголовок RecvBytes = Recv (acpt, FILEDATA, sizeof (FILEDATA), 0); // Получает заголовки и содержимое файлов char * namePtr = strstr(FILEDATA,"\r\n\r\n"); namePtr = strstr(FILEDATA,"filename=\"") + strlen("filename "); // Здесь начинается извлечение имени файла while(namePtr[x]!='"'){ х++; } strncpy(FileName,namePtr,x); // На этом извлечение имени файла заканчивается. printf("ИМЯ: %s\n\n",FileName); int NumberOfBytes = (&strstr(FILEDATA,"\r\n\r\n")[0]+2 - &FILEDATA[0])+2; е = fopen(ИмяФайла,"wb"); //Открываем файл для записи fwrite(strstr(FILEDATA,"\r\n\r\n")+3,1,RecvBytes - NumberOfBytes,f); // Число полученных байтов - Количество байт до заголовка while(select(acpt+1,&rfd,NULL,NULL,&DownloadTimeout)){ // Продолжайте читать, если доступны дополнительные данные RecvBytes = Recv (acpt, FILEDATA, sizeof (FILEDATA), 0); // получать если (RecvBytes == 0) { перерыв; } fwrite(FILEDATA,1,RecvBytes,f); } } fзакрыть (е); unsigned long long truncFile = FileSize(FileName) - 45; f = fopen(ИмяФайла,"r+"); // усечение файла для удаления подстроки границы веб-кита в конце файла. ftruncate (fileno (f), truncFile); fзакрыть (е); printf("РАЗМЕР ВЫХОДНОГО ФАЙЛА: %llu\n\n",FileSize(FileName)); MessageBeep (MB_ICONERROR); // Звуковой сигнал означает, что операция завершена выключение (принятие, 2); closesocket(acpt); closesocket(сокт); выключение (соц, 2); акпт = NULL; соц = NULL; memset(FILEDATA,'\0',sizeof(FILEDATA)); } интервал основной(){ //printf("%d\n",strlen("------WebKitFormBoundary5BlPHcjSKYuZFzV3--")); 42 WSAStartup(MAKEWORD(2,2),&ws); пока(1){ Служить(); } вернуть 0; } Теперь HTML-страница AJAX, используемая для загрузки,
Содержимое элемента body отображается в вашем браузере. Отправить функция Отправить(){ let photo = document.getElementById("файл-изображения").files[0]; // файл из ввода пусть req = новый XMLHttpRequest(); пусть formData = новый FormData(); formData.append("фото", фото); req.open("POST", 'http://localhost:12345/'); req.send(formData); } Мне хотелось бы как можно быстрее решить эту проблему. Спасибо за понимание моего беспокойства. С уважением...
По некоторым причинам и в образовательных целях я разработал с нуля HTTP-сервер C++, который должен перехватывать загрузки файлов со страницы HTML с помощью AJAX, обрабатывающего динамические запросы, и сохранять их в том же каталоге, где находится серверная программа.
>
Сервер отлично работает с файлами .txt. Файлы загружаются и сохраняются в каталоге сервера без каких-либо ошибок. Все остается идеальным, но проблема начинается, когда я пытаюсь загрузить двоичные файлы, такие как исполняемые файлы, видеофайлы, музыкальные файлы и другие. По сути, сервер работает нормально с файлами .txt, а не с другими. Всякий раз, когда загружается двоичный файл, выходной файл на стороне сервера каким-то образом повреждается.
Я знаю, что для этих операций существуют платформы PHP и NodeJS, но на самом деле я буду развертывать этот проект на чистом сервере контроллера, который имеет очень ограниченное количество ресурсов, которые не могут противостоять сложным платформам. Таким образом, сервер C++ с использованием нуля кажется единственным способом достижения моей цели. Хоть я и не могу напрямую портировать этот код в контроллер, процедура остаётся прежней. Чтобы узнать об этой процедуре из первых рук, мне придется провести несколько экспериментов в Windows с использованием Windows Sockets.
Вот что я уже пробовал
Код HTTP-сервера C++.
#include #include #include #include #include #include #include #include #define ПОРТ 12345 ВСАДАТА ws; символ Команда [8888]; char FILEDATA[(2 * 1024)]; // ЗАГОЛОВОК ФАЙЛА и БУФЕР SOCKET соц, акцепт; ФАЙЛ *f ; беззнаковый длинный длинный FileSize(char * direc){ беззнаковый длинный длинный размер = 0; ФАЙЛ *fsize = fopen(direc,"rb"); fseek(fsize,0,SEEK_END); размер = _ftelli64 (fsize); fseek(fsize,0,SEEK_SET); fзакрыть (размер); размер возврата; } недействительный Служить () { интервал optval = 1; интервал RecvBytes = 0; sockaddr_in адрес, адрес узла; struct timeval RequestTimeout = {0,5000000}, DownloadTimeout = {0,500000}; символьный 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(ПОРТ); fd_set РФД; FD_ZERO(&rfd); soc = сокет (AF_INET, SOCK_STREAM, IPPROTO_TCP); setockopt(soc,SOL_SOCKET,SO_REUSEADDR,(const char*)&optval,sizeof(optval)); связывание(soc,(sockaddr*)&addr,sizeof(addr)); слушать (соц, 100); акпт = принять (сок, NULL, NULL); FD_SET(принять,&rfd); int connstat = select(acpt+1,&rfd,NULL,NULL,&RequestTimeout); // действуем только в том случае, если можно выполнить стабильное чтение если (connstat) { интервал х = 0; RecvBytes = Recv(acpt,Command,sizeof(Command),0); // Получает HTTP-заголовок RecvBytes = Recv (acpt, FILEDATA, sizeof (FILEDATA), 0); // Получает заголовки и содержимое файлов char * namePtr = strstr(FILEDATA,"\r\n\r\n"); namePtr = strstr(FILEDATA,"filename=\"") + strlen("filename "); // Здесь начинается извлечение имени файла while(namePtr[x]!='"'){ х++; } strncpy(FileName,namePtr,x); // На этом извлечение имени файла заканчивается. printf("ИМЯ: %s\n\n",FileName); int NumberOfBytes = (&strstr(FILEDATA,"\r\n\r\n")[0]+2 - &FILEDATA[0])+2; е = fopen(ИмяФайла,"wb"); //Открываем файл для записи fwrite(strstr(FILEDATA,"\r\n\r\n")+3,1,RecvBytes - NumberOfBytes,f); // Число полученных байтов - Количество байт до заголовка while(select(acpt+1,&rfd,NULL,NULL,&DownloadTimeout)){ // Продолжайте читать, если доступны дополнительные данные RecvBytes = Recv (acpt, FILEDATA, sizeof (FILEDATA), 0); // получать если (RecvBytes == 0) { перерыв; } fwrite(FILEDATA,1,RecvBytes,f); } } fзакрыть (е); unsigned long long truncFile = FileSize(FileName) - 45; f = fopen(ИмяФайла,"r+"); // усечение файла для удаления подстроки границы веб-кита в конце файла. ftruncate (fileno (f), truncFile); fзакрыть (е); printf("РАЗМЕР ВЫХОДНОГО ФАЙЛА: %llu\n\n",FileSize(FileName)); MessageBeep (MB_ICONERROR); // Звуковой сигнал означает, что операция завершена выключение (принятие, 2); closesocket(acpt); closesocket(сокт); выключение (соц, 2); акпт = NULL; соц = NULL; memset(FILEDATA,'\0',sizeof(FILEDATA)); } интервал основной(){ //printf("%d\n",strlen("------WebKitFormBoundary5BlPHcjSKYuZFzV3--")); 42 WSAStartup(MAKEWORD(2,2),&ws); пока(1){ Служить(); } вернуть 0; } Теперь HTML-страница AJAX, используемая для загрузки,
Содержимое элемента body отображается в вашем браузере. Отправить функция Отправить(){ let photo = document.getElementById("файл-изображения").files[0]; // файл из ввода пусть req = новый XMLHttpRequest(); пусть formData = новый FormData(); formData.append("фото", фото); req.open("POST", 'http://localhost:12345/'); req.send(formData); } Мне хотелось бы как можно быстрее решить эту проблему. Спасибо за понимание моего беспокойства. С уважением...
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Какой стек HTTP для использования для клиента, требующего HTTP/1.1, HTTP/2 и HTTP/3
Anonymous » » в форуме Android - 0 Ответы
- 65 Просмотры
-
Последнее сообщение Anonymous
-
-
-
«Вы забыли добавить плагин «mini-css-extract-plugin» при работе с потоковым загрузчиком
Anonymous » » в форуме CSS - 0 Ответы
- 54 Просмотры
-
Последнее сообщение Anonymous
-