2016-04-29 11 views
-5

WindowsソケットHTTPを使用してPHPスクリプトにPNGイメージをアップロードしようとしました。すべてがうまくいくようですが、Windows Paintで画像を開こうとすると、エラーメッセージが表示されます。イメージC++のHTTPアップロードが壊れています

これは有効なビットマップファイルではありません。

私は何が間違っているのか分かりません。私はHTTPヘッダーフィールドに少し新しいので、私の推測では、ヘッダーが間違っている可能性があります。これを引き起こす原因は何ですか?

C++コード(original C++ pastebin link):

#include <iostream> 
#include <winsock2.h> 
#include <string> 
#include <fstream> 
#include "windows.h" 
#include "stdio.h" 

using namespace std; 

#define PORT  80 
#define IP   "127.0.0.1" 
#define HOST  "locahost" 
#define RECEIVER "/up.php" 
#define COMPNAME "compname" 
#define PROGRAM "program" 
#define FILENAME "file" 
#define BOUNDARY "----------boundary" 
#define DUMMY_DATA "c2FzYXNhc2FzZGRmZGZkY2Q=" 
#define DUMMY_FILE "ok.png" 

//------------------------------------ 
string constructBody(string args[2], string file[2]); 
string readFile(string fileName); 
//------------------------------------ 

int main() { 
    // initiate the socket! 
    SOCKET dataSock; 
    WSADATA wsaData; 
    int error = WSAStartup(0x0202, &wsaData); 
    if (error != 0) { 
     WSACleanup(); 
     exit(1); // oh shit, this shouldn't happen! 
    } 
    // all internets, engage! 
    SOCKADDR_IN target; 
    target.sin_family = AF_INET; 
    target.sin_port = htons(PORT); 
    target.sin_addr.s_addr = inet_addr(IP); 
    dataSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
    if (dataSock == INVALID_SOCKET) { 
     exit(1); // Houston, we have a problem! 
    } 
    connect(dataSock, (SOCKADDR*)&target, sizeof(target)); 

    string programNames[5][2] = {{"Browser", "Mozilla"}}; 
    string file[2] = {FILENAME, "Default.txt"}; 

    for (int i = 0; i < 1; i++) { 
     printf("Sending data for %s\n", (programNames[i][1]).c_str()); 
     string body = constructBody(programNames[i], file); 
     char header[1024]; 
     sprintf(header, "POST %s HTTP 1.1\r\n" 
         "Host: %s\r\n" 
         "Content-Length: %d\r\n" 
         "Connection: Keep-Alive\r\n" 
         "Content-Type: multipart/form-data; boundary=%s\r\n" 
         "\r\n", RECEIVER, IP, strlen(body.c_str()), BOUNDARY); 
//  printf("%s\n\n", header); 
     int p = send(dataSock, header, strlen(header), 0); 
//  printf("p == %d\n", p); 
     int k = send(dataSock, body.c_str(), strlen(body.c_str()), 0); 
//  printf("k == %d\n", k); 

     char buff[1024]; 
     recv(dataSock, buff, 1024, 0); 
     printf("%s\n\n", buff); 
    } 

    closesocket(dataSock); 
    WSACleanup(); 
} 

string readFile(string fileName) { 
    string fileContents; 
    ifstream tmp(fileName.c_str()); 
    getline(tmp, fileContents); 
    tmp.close(); 

    return fileContents; 
} 

string constructBody(string args[2], string file[2]) { 
    string body; 
    string CRLF = "\r\n"; 

    // first we add the args 
    body.append("--"+string(BOUNDARY)+CRLF); 
    body.append("Content-Disposition: form-data; name=\""+string(COMPNAME)+"\""+CRLF); 
    body.append(CRLF); 
    body.append(args[0]+CRLF); 
    body.append("--"+string(BOUNDARY)+CRLF); 
    body.append("Content-Disposition: form-data; name=\""+string(PROGRAM)+"\""+CRLF); 
    body.append(CRLF); 
    body.append(args[1]+CRLF); 

    // now we add the file 
    body.append("--"+string(BOUNDARY)+CRLF); 
    body.append("Content-Disposition: form-data; name=\""+string(FILENAME)+"\"; filename=\""+string(DUMMY_FILE)+"\""+CRLF); 
    body.append("Content-Type: media-type"+CRLF); 
    body.append(CRLF); 
    body.append(DUMMY_DATA+CRLF); 
    body.append("--"+string(BOUNDARY)+"--"+CRLF); 
    body.append(CRLF); 

// printf(body.c_str()); exit(0); 

    return body; 
} 

PHPコード(original PHP pastebin link):

<?php 
/* ===== CONSTANTS ===== */ 
$ROOT_DIR = 'FILES'; 
$COMPUTER_NAME = 'compname'; 
$PROGRAM = 'program'; 
$FILENAME = 'file'; 
$CHUNK_SIZE = 1024; 
/* ===================== */ 

//===================================== 
/** 
    Function that gets current time and formats it into pretty looking date 
*/ 
function makeDate() { 
    return strftime('%Y-%m-%d, %H.%M'); 
} 
//===================================== 
// check here if the parameters are set. If it's not then it's safe to say some one is snooping around... 
if (isset($_POST[$COMPUTER_NAME], $_POST[$PROGRAM], $_FILES[$FILENAME])) { 
    // construct a full path and create it 
    $fullPath = $ROOT_DIR.'\\'.$_POST[$COMPUTER_NAME].'\\'.$_POST[$PROGRAM].'\\'.makeDate(); 
    mkdir($fullPath, 0777, true); 

    // move the files and rename them as temporary 
    $filename = $_FILES[$FILENAME]['name']; 
    move_uploaded_file(($_FILES[$FILENAME]['tmp_name']), $fullPath.'\\'.$filename.'.tmp'); 

    // decode received files 
    $src = fopen($fullPath.'\\'.$filename.'.tmp', 'rb'); 
    $dst = fopen($fullPath.'\\'.$filename, 'wb'); 
    while (!feof($src)) { 
     fwrite($dst, base64_decode(fread($src, $CHUNK_SIZE))); 
    } 
    fclose($dst); 
    fclose($src); 
    unlink($fullPath.'\\'.$filename.'.tmp'); // remove the temp file after decoding it 

    echo 'OK!'; 
} else { 
    echo 'oh no :('; 
} 
//===================================== 
?> 
+3

[最小限で完全であり、検証可能な例]を提供してください(http://stackoverflow.com/help/mcve) – teivaz

答えて

0

少なくとも、C++コードは、テキストファイルとしての.pngファイルを読んでいますその内容をヌルで終わる文字列として扱います。それはまた、最初の行末までしか読んでいないようです。あなたがしたいのは、.pngファイルのバイナリ読み取りです。

このexampleと同じバイナリ読み取り機能を使用するようにreadFile()関数を変更してみてください。

この例では、適切なサイズのバッファを割り当てるためにファイルサイズが最初に読み取られることに注意してください。手動でバッファ管理を扱いたくないかもしれないので、代わりにvector<char>を使用するように選択すると、関連付けられたメモリリソースが割り当てられ/解放されます。 vector<>のリファレンスガイドについては、linkを参照してください。このような

何かがあなたが望むものに近いものがあります。これらの変更により

bool readFile(string fileName, vector<char> &fileContents) { 
    vector<char> fileContents; 
    std::ifstream is (fileName.c_str(), std::ifstream::binary); 
    bool success = is; 

    if (success) { 
     // get length of file: 
     is.seekg (0, is.end); 
     int length = is.tellg(); 
     is.seekg (0, is.beg); 

     fileContents.resize(length); 
     is.read(fileContents, length); 
     is.close(); 
    } 

    return success; 
} 

、あなたがreadFile()を呼び出す方法を変更する必要があります。あなたが投稿したコードでreadFile()が実際に呼び出されることはありませんので、fileContentsという変数を宣言してreadFile()を呼び出すという点がconstructBody()にあります。

readFile()のこの使用考えてみましょう:後で同じ機能で

vector<char> fileContents; 
bool success = readFile(filename, fileContents); 

を、あなたは出力にbodyバッファにfileContentsをお勧めします。

fileContentsと同様に、body変数は、付随するヌル終了を避けるため、stringであってはいけません。この場合にはvector<char>を使用する方が良いでしょう。body.append()へのすべての呼び出しは、コンテンツと行末を正しく追加するために更新する必要があります。それは簡単なはずですが、まだ完了するには追加作業が必要です。

これは、.pngファイルを読み込んで送信する際の最初の大きな問題となるため、PHPコードについて詳しくは解説していません。それがまったく別のものかどうか。 PHPコードで受け取ったファイルの内容が元の.pngファイルの実際の内容と一致するようにして、デバッグ出力を提供することができます。それらが一致するまでは、C++コードでは依然として問題となる可能性があります。

関連する問題