2017-11-11 15 views
1

Apache2ウェブサーバ上で実行されているPHPアプリケーションを使用してファイルをアップロードしようとしているC++プログラムがあります。私は何をすべきかわからない非常に奇妙な問題を抱えています。したがって、httpSendRequest()関数を使用してHTTPリクエストを作成し、wireshark wireshark imageで表示すると適切にフォーマットされているように見えます。しかし、ファイルはアップロードされていません.APIのaccess.logファイルを見ると、明らかに両方のパケットキャプチャにもかかわらず、ユーザーエージェントやコンテンツの長さは表示されません。 apache error imageApache2のaccess.logが同じパケットの場合

参考として、200ステータスを返すリクエストは、httpSendRequestを使用する私のプログラムの代わりに、burp suiteを使って送信されたものと同じです。また、Webブラウザを使用してファイルをアップロードすることもできます。

httpSendRequestを使用してリクエストを作成するコードは、ほとんどがthis codeguru postから直接取得されています。

#include <windows.h> 
#include <wininet.h> 
#include <iostream> 


#define ERROR_OPEN_FILE  10 
#define ERROR_MEMORY   11 
#define ERROR_SIZE   12 
#define ERROR_INTERNET_OPEN 13 
#define ERROR_INTERNET_CONN 14 
#define ERROR_INTERNET_REQ 15 
#define ERROR_INTERNET_SEND 16 

using namespace std; 

int main() 
{ 
    // Local variables 
    static char *filename = "test.txt"; //Filename to be loaded 
    static char *type  = "image/jpg"; 
    static char boundary[] = "PaulRules";   //Header boundary 
    static char nameForm[] = "fileToUpload";  //Input form name 
    static char iaddr[]  = "192.168.0.105";  //IP address 
    static char url[]  = "upload.php";   //URL 

    char hdrs[255];     //Headers 
    char * buffer;     //Buffer containing file + headers 
    char * content;     //Buffer containing file 
    FILE * pFile;     //File pointer 
    long lSize;      //File size 
    size_t result; 


    // Open file 
    pFile = fopen (filename , "rb"); 
    if (pFile==NULL) return ERROR_OPEN_FILE; 

    // obtain file size: 
    fseek (pFile , 0 , SEEK_END); 
    lSize = ftell (pFile); 
    rewind (pFile); 

    // allocate memory to contain the whole file: 
    content = (char*) malloc (sizeof(char)*lSize); 
    if (content == NULL) return ERROR_MEMORY; 

    // copy the file into the buffer: 
    result = fread (content,1,lSize,pFile); 
    if (result != lSize) return ERROR_SIZE; 

    // terminate 
    fclose (pFile); 

    //allocate memory to contain the whole file + HEADER 
    buffer = (char*) malloc (sizeof(char)*lSize + 2048); 

    //print header 
    sprintf(hdrs,"Content-Type: multipart/form-data; boundary=%s",boundary); 
    sprintf(buffer,"--%s\r\nContent-Disposition: form-data; name=\"fileToUpload\"; filename=\"test.bmp\"\r\n",boundary,nameForm,filename); 
    sprintf(buffer,"%sContent-Type: %s\r\n\r\n",buffer,type); 

    int cb = strlen(buffer); 
    char * bp = buffer + cb; 
    memcpy(bp, content, lSize); 
    bp += lSize; 
    int cw = sprintf(bp,"\r\n--%s--\r\n",boundary); 

    //Open internet connection 
    HINTERNET hSession = InternetOpen("Paul was here :)",INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); 
    if(hSession==NULL) return ERROR_INTERNET_OPEN; 

    HINTERNET hConnect = InternetConnect(hSession, iaddr,INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1); 
    if(hConnect==NULL) return ERROR_INTERNET_CONN; 

    HINTERNET hRequest = HttpOpenRequest(hConnect, (const char*)"POST",url, NULL, NULL, (const char**)"*/*", 0, 1); 
    if(hRequest==NULL) return ERROR_INTERNET_REQ; 

    BOOL sent= HttpSendRequest(hRequest, hdrs, strlen(hdrs), buffer, cb + lSize + cw); 
    if(!sent) return ERROR_INTERNET_SEND; 

    //close any valid internet-handles 
    InternetCloseHandle(hSession); 
    InternetCloseHandle(hConnect); 
    InternetCloseHandle(hRequest); 

    return 0; 
} 

そして、ここでは、PHPスクリプトがサーバー側にある

<?php 
$target_dir = "recvFile/"; 
$target_file = $target_dir . basename($_FILES["fileToUpload"]["name"]); 
$uploadOk = 1; 
$imageFileType = pathinfo($target_file,PATHINFO_EXTENSION); 

// Check if file already exists 
if (file_exists($target_file)) { 
    echo "File already exists"; 
    $uploadOk = 0; 
} 

// Check file size 
if ($_FILES["fileToUpload"]["size"] > 500000) { 
    echo "File to large"; 
    $uploadOk = 0; 
} 

// Check if $uploadOk is set to 0 by an error 
if ($uploadOk == 0) { 
    echo "ERROR File not uploaded"; 
} 

//attempt to upload the file 
else { 
    if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file)) { 
     //echo "The file ". basename($_FILES["fileToUpload"]["name"]). " has been uploaded."; 
     echo "Command:1"; 
    } 
    else { 
     echo $_FILES["fileToUpload"]["tmp_name"]; 
     echo "ERROR uploading file"; 
    } 
} 
?> 
+0

はありコロンはUser-Agentの製品トークンの合法的な文字ですアン? – IInspectable

+0

@IInspectable私はそれが合法だと確信していますが、とにかくそれが不要なので、私はそれを取り除きました。同じ問題が残っているにもかかわらず。 – pchihak

答えて

1

ソースファイルは"test.txt"ですが、あなたは"test.bmp"にアップロードされています。同じ拡張子にします。 "image/*"または"text/*"

type = "image/jpg"; 

変更typeこれはテキストことになっている場合。

あなたの操作はおそらく、それが"Command 1"を印刷しているのを見て成功しています。ファイルはおそらくそこにありますが、あなたが期待するものではありません。そうでない場合は、PHP側からどのようなエラーを抽出できるかを確認してください。

sprintf(buffer,"--%s\r\nContent-Disposition: form-data; \ 
name=\"fileToUpload\"; filename=\"test.bmp\"\r\n", 
boundary,nameForm,filename); 

1つの書式指定子"%s"と4つのパラメータがあります。最後の2つのパラメータを削除します。

使用HttpOpenRequestそれが推奨される方法:ただ完全を期すためにC++

#include <Windows.h> 
#include <Wininet.h> 
#include <iostream> 
#include <fstream> 
#include <sstream> 
#include <string> 

#pragma comment(lib, "wininet.lib") 

int main() 
{ 
    HINTERNET hsession = NULL; 
    HINTERNET hconnect = NULL; 
    HINTERNET hrequest = NULL; 

    const char* server = "localhost"; 
    const char* url = "upload.php"; 
    const char* type = "image/*"; 
    std::string filename = "test.bmp"; 

    std::ifstream infile("c:\\test\\test.bmp", std::ios::binary); 
    if(!infile) 
     return 0; 

    std::ostringstream oss; 
    oss << infile.rdbuf(); 

    std::string headers = "Content-type: multipart/form-data, boundary=uniquestring"; 

    std::string data = "--uniquestring\r\n\ 
Content-Disposition: form-data; name=\"fileToUpload\"; filename=\"%1\"\r\n\ 
Content-Type: %2\r\n\ 
\r\n\ 
%3\r\n\ 
--uniquestring--"; 

    data.replace(data.find("%1"), 2, filename); 
    data.replace(data.find("%2"), 2, type); 
    data.replace(data.find("%3"), 2, oss.str()); 

    hsession = InternetOpen("appname", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); 
    if(!hsession) 
     goto cleanup; 

    hconnect = InternetConnect(hsession, server, INTERNET_DEFAULT_HTTP_PORT, 
     NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1); 
    if(!hconnect) 
     goto cleanup; 

    const char *accept[] = { type, NULL }; 
    hrequest = HttpOpenRequest(hconnect, "POST", url, NULL, NULL, accept, 0, 1); 
    if(!hrequest) 
     goto cleanup; 

    BOOL sent = HttpSendRequest(hrequest, headers.data(), headers.size(), 
     &data[0], data.size()); 
    if(sent) 
    { 
     DWORD bufsize = 4096; 
     std::string read(bufsize, 0); 
     InternetReadFile(hrequest, &read[0], bufsize, &bufsize); 
     read.resize(bufsize); 
     std::cout << read << "\n"; 
    } 
    else 
    { 
     goto cleanup; 
    } 

cleanup: 
    if(hrequest) InternetCloseHandle(hrequest); 
    if(hconnect) InternetCloseHandle(hconnect); 
    if(hsession) InternetCloseHandle(hsession); 
    return 0; 
} 
+0

.jpgとして.txtファイルをアップロードしようとしたときに、サーバーが壊れていたのは確かです。私は本当にそれを感謝するすべてのおかげで、ありがとう! – pchihak

+0

よかった。ところであなたのコードはC言語ですが、私はC++ 11のコードを追加しています。 –

1

を使用して

const char *accept[] = { "image/*", NULL }; // or `"text/*"` 
HttpOpenRequest(hConnect, "POST",url, NULL, NULL, accept, 0, 1); 


コードここで完全に動作するコードは

#include <windows.h> 
#include <wininet.h> 
#include <iostream> 

using namespace std; 
int main() 
{ 
    // Local variables 
    static char *filename = "Desert.jpg"; //Filename to be loaded 
    static char *type  = "multipart/form-data"; 
    static char boundary[] = "PaulRules";   //Header boundary 
    static char nameForm[] = "fileToUpload";  //Input form name 
    static char iaddr[]  = "192.168.0.105";  //IP address 
    static char url[]  = "upload.php";   //URL 

    char hdrs[255];     //Headers 
    char * buffer;     //Buffer containing file + headers 
    char * content;     //Buffer containing file 
    FILE * pFile;     //File pointer 
    long lSize;      //File size 
    size_t result; 


    // Open file 
    pFile = fopen (filename , "rb"); 

    // obtain file size: 
    fseek (pFile , 0 , SEEK_END); 
    lSize = ftell (pFile); 
    rewind (pFile); 

    // allocate memory to contain the whole file: 
    content = (char*) malloc (sizeof(char)*lSize); 

    // copy the file into the buffer: 
    result = fread (content,1,lSize,pFile); 

    // terminate 
    fclose (pFile); 

    //allocate memory to contain the whole file + HEADER 
    buffer = (char*) malloc (sizeof(char)*lSize + 2048); 

    //print header 
    sprintf(hdrs,"Content-Type: multipart/form-data; boundary=%s",boundary); 
    sprintf(buffer,"--%s\r\nContent-Disposition: form-data; name=\"fileToUpload\"; filename=\"%s\"\r\n",boundary, filename); 
    sprintf(buffer,"%sContent-Type: %s\r\n\r\n",buffer,type); 

    int cb = strlen(buffer); 
    char * bp = buffer + cb; 
    memcpy(bp, content, lSize); 
    bp += lSize; 
    int cw = sprintf(bp,"\r\n--%s--\r\n",boundary); 

    //Open internet connection 
    HINTERNET hSession = InternetOpen("Winsock",INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); 

    HINTERNET hConnect = InternetConnect(hSession, iaddr,INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1); 

    const char* accept[] = {"*/*", NULL}; 
    HINTERNET hRequest = HttpOpenRequest(hConnect, (const char*)"POST",url, NULL, NULL, accept, 0, 1); 

    BOOL sent= HttpSendRequest(hRequest, hdrs, strlen(hdrs), buffer, cb + lSize + cw); 

    DWORD dwSize, dwRead; 
    CHAR szBuffer[1024]; 
    if(!InternetQueryDataAvailable(hRequest, &dwSize, 0, 0)){ 
     std::cout << "QUERYDATA ERROR: " << GetLastError() << std::endl; 
    } 
    else{ 
     while(InternetReadFile(hRequest, szBuffer, sizeof(szBuffer)-1, &dwRead) && dwRead) { 
     szBuffer[dwRead] = 0; 
     dwRead=0; 
     } 
     cout << szBuffer; 
    } 

    //close any valid internet-handles 
    InternetCloseHandle(hSession); 
    InternetCloseHandle(hConnect); 
    InternetCloseHandle(hRequest); 

    return 0; 
} 
関連する問題