2017-11-25 17 views
0

私のサーバーにファイルを送信する際に問題があります。私はいくつかの他の質問は、問題のほとんどを解決しようとしたチェックインしたが、最後に私はここでファイル をアップロードすることはできませんよ、私のC++コードです。ここでPOSTでファイルを送信する[アップロードできません] C++で

#define _CRT_SECURE_NO_WARNINGS 
#include <windows.h> 
#include <wininet.h> 
#include <iostream> 
#include <tchar.h> 
#pragma warning(disable : 4996) 
#pragma comment(lib,"wininet.lib") 
#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 = "perf.txt"; //Filename to be loaded 
    static char *filepath = "C:\\perf.txt"; //Filename to be loaded 
    static char *type = "text/plain"; 
    static char boundary[] = "BOUNDARY";   //Header boundary 
    static char nameForm[] = "file";  //Input form name 
    static char iaddr[] = "2e8cd930.ngrok.io";  //IP address 
    static char url[] = "/post/upload.php";   //URL 

    char hdrs[512] = { '-' };     //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(filepath, "rb"); 
    if (pFile == NULL) 
    { 
     printf("ERROR_OPEN_FILE"); 
     getchar(); 
     return ERROR_OPEN_FILE; 
    } 
    printf("OPEN_FILE\n"); 

    // 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 + 1)); 
    if (content == NULL) 
    { 
     printf("ERROR_MEMORY"); 
     getchar(); 
     return ERROR_OPEN_FILE; 
    } 
    printf("MEMORY_ALLOCATED\t \"%d\" \n", &lSize); 
    // copy the file into the buffer: 
    result = fread(content, 1, lSize, pFile); 
    if (result != lSize) 
    { 
     printf("ERROR_SIZE"); 
     getchar(); 
     return ERROR_OPEN_FILE; 
    } 
    printf("SIZE_OK\n"); 

    content[lSize] = '\0'; 

    // terminate 
    fclose(pFile); 
    printf("FILE_CLOSE\n"); 
    //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=\"%s\"; filename=\"%s\"\r\n", boundary, nameForm, filename); 
    sprintf(buffer, "%sContent-Type: %s\r\n", buffer, type); 
    sprintf(buffer, "%s\r\n\r\n%s", buffer, content); 
    sprintf(buffer, "%s\r\n-%s-\r\n", buffer, boundary); 

    printf("%s", buffer); 

    //Open internet connection 
    HINTERNET hSession = InternetOpen("WINDOWS", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); 
    if (hSession == NULL) 
    { 
     printf("ERROR_INTERNET_OPEN"); 
     getchar(); 
     return ERROR_OPEN_FILE; 
    } 
    printf("INTERNET_OPENED\n"); 

    HINTERNET hConnect = InternetConnect(hSession, iaddr, INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1); 
    if (hConnect == NULL) 
    { 
     printf("ERROR_INTERNET_CONN"); 
     getchar(); 
     return ERROR_INTERNET_CONN; 
    } 
    printf("INTERNET_CONNECTED\n"); 

    HINTERNET hRequest = HttpOpenRequest(hConnect, (const char*)"POST", _T(url), NULL, NULL, NULL, INTERNET_FLAG_RELOAD, 1); 
    if (hRequest == NULL) 
    { 
     printf("ERROR_INTERNET_REQ"); 
     getchar(); 

    } 
    printf("INTERNET_REQ_OPEN\n"); 

    BOOL sent = HttpSendRequest(hRequest, hdrs, strlen(hdrs), buffer, strlen(buffer)); 

    if (!sent) 
    { 
     printf("ERROR_INTERNET_SEND"); 
     getchar(); 
     return ERROR_INTERNET_CONN; 
    } 
    printf("INTERNET_SEND_OK\n"); 

    InternetCloseHandle(hSession); 
    InternetCloseHandle(hConnect); 
    InternetCloseHandle(hRequest); 

    getchar(); 
    return 0; 
} 

私のPHPコードは[upload.php]で、私はすでにファイルを作成および削除するために、他のアップロードフォルダのアクセス権を変更しました:

<?php 
$uploaddir = 'upload/'; 

if (is_uploaded_file(isset($_FILES['file']['tmp_name'])?($_FILES['file'['tmp_name']]):0)) 
{ 
    $uploadfile = $uploaddir . basename($_FILES['file']['name']); 
    echo "File ". $_FILES['file']['name'] ." uploaded successfully. "; 

    if (move_uploaded_file($_FILES['file']['tmp_name'], $uploadfile)) 
    { 
     echo "File was moved! "; 
    } 
    else 
    { 
     print_r($_FILES); 
    } 
} 
else 
{ 
    print_r($_FILES); 
} 
?> 

を私のPOSTリクエストとレスポンスは、[私はすでにコンテンツ型ラインの後に1行を持つ2つの新しい行を交換しようとしましたが、助けていないされてWiresharkのを使用して デリミタを変更した後:

POST /post/upload.php HTTP/1.1 
Content-Type: multipart/form-data; boundary=BOUNDARY 
User-Agent: WINDOWS 
Host: 2e8cd930.ngrok.io 
Content-Length: 130 
Cache-Control: no-cache 

-BOUNDARY 
Content-Disposition: form-data; name="file"; filename="perf.txt" 
Content-Type: text/plain 


Whats Up? 
-BOUNDARY- 
HTTP/1.1 200 OK 
Date: Sat, 25 Nov 2017 11:25:16 GMT 
Server: Apache/2.4.27 (Debian) 
Content-Length: 10 
Content-Type: text/html; charset=UTF-8 

Array 
(
) 

私のサーバーがArray()で返信する理由がわかりません。ファイルがアップロードされていません。私が見ることができる

+0

少なくとも、閉じた区切り記号とヘッダーの区切り記号が間違っています。 - 境界の一部ではないので、ヘッダーから削除します。終了区切り文字も必要です。あなたのsprintfsも新しいデータを追加するのではなく、既存のデータを何度も何度もコピーするので悪いです。そしてあなたは体の前に\ rを見逃しています。 –

+0

申し訳ありませんが、私はあなたが意味するものを理解できません。私は理解することができるように、コードを精巧に編集することができますか? –

答えて

0

最初の問題:区切り文字が—BOUNDARYで、その後、実際の区切り文字と同じ文字列を使用して、あなたのヘッダーにあなたが言う

。これは間違っています。形式は

—DELIMITER 
content 
—DELIMITER 
content 
—DELIMITER— 

です。したがって、ヘッダーは区切り文字としてちょうどBOUNDARYと言う必要があります。

Content-Type: multipart/form-data; boundary=BOUNDARY 

さらに、末尾のを終了区切り文字に追加する必要があります。

また、本体とヘッダーを分離するときには\r\n\nとなります。 \r\n\r\nである必要があります。

これらのエラーは、MIMEパーサーがどこでもフォームデータを見つけられないようにします。

パフォーマンス面では、バッファを先に配置して追加するデータを追加する場合は、sprintfを使用しないでください。それはあまりにもすでにそこにあるデータをコピーする方法を引き起こすでしょう。すべてが追加される文字列ではなく、strncatを使用してください。または、文字列の長さを監視し、最後にsprintfを使用して追加します。詳細については、this questionを参照してください。

+0

私は区切り文字を変更しましたが、私の更新された要求は上記ですが、まだファイルをアップロードできませんか?なにか提案を –

関連する問題