2013-07-08 29 views
2

我正在開發一個小型項目,該項目將使用C++應用程序發送一個文件(圖像),並通過網頁服務器接收它http(no ftp )。用C/C++中的winsocks發送原始請求(http post文件數據)

我用winsocks發送的查詢,但我的問題是:

std::string query= 
    "POST /test/upload.php HTTP/1.1\r\n" 
    "Host: site.net\r\n" 
    "User-Agent: User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36\r\n" 
    "Connection: Keep-alive\r\n\r\n" 
    "Content-Length: "+FileSize+"\r\n" 
    "Content-Type: multipart/form-data; boundary=----WebKitFormBoundarym9PgiUg6fjxm2Hpr\r\n" 

    "------WebKitFormBoundarym9PgiUg6fjxm2Hpr\r\n" 
     "Content-Disposition: form-data; name=\"tmp\"; filename=\"photo.jpg\"\r\n" 
     "Content-Type: image/jpeg\r\n\r\n" 
     +StrData+ 
    "------WebKitFormBoundarym9PgiUg6fjxm2Hpr--\r\n"; 

我要在這裏把我的文件的HEX - >strData是,但我不知道該怎麼辦那??

回答

2

不,您不需要以十六進制發送文件數據。您需要原樣發送文件的原始二進制數據。假設文件的大小很小,可以按原樣將它填入std::string

順便說一下,您的請求格式錯誤 - 您在Connection標頭上有太多\r\n。額外的\r\n屬於最後一個標題之後。並且不要使用Content-Length標題和multipart內容類型,因爲它們是自行終止的 - 尤其是因爲您無論如何都指定了錯誤的值。如果您要指定Content-Length,則必須先計算完整MIME數據的長度,然後再創建用於處理它的標頭。

試試這個:

std::ifstream File("filename", std::ios::in | std::ios::binary | std:::ios::ate); 
if (file) 
{ 
    std::ifstream::pos_type FileSize = File.tellp(); 
    File.seekg(0); 

    std::string StrData; 
    if (FileSize > 0) 
    { 
     StrData.resize(FileSize); 
     File.read(&StrData[0], FileSize); 
    } 

    File.close(); 

    std::string query = 
     "POST /test/upload.php HTTP/1.1\r\n" 
     "Host: site.net\r\n" 
     "User-Agent: User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36\r\n" 
     "Connection: Keep-alive\r\n" 
     "Content-Type: multipart/form-data; boundary=----WebKitFormBoundarym9PgiUg6fjxm2Hpr\r\n" 
     "\r\n" 
     "------WebKitFormBoundarym9PgiUg6fjxm2Hpr\r\n" 
     "Content-Disposition: form-data; name=\"tmp\"; filename=\"photo.jpg\"\r\n" 
     "Content-Type: image/jpeg\r\n" 
     "\r\n" 
     +StrData+ 
     "\r\n" 
     "------WebKitFormBoundarym9PgiUg6fjxm2Hpr--\r\n"; 

    // send query ... 
} 

雖這麼說,還是不要嘗試的東西整個HTTP請求到一個單一的std::string。首先發送初始請求頭,然後發送原始文件數據,然後發送終止邊界。例如:

std::fstream File("filename", std::ios::in | std::ios::binary); 
if (file) 
{ 
    char chunk[1024]; 
    std::streamsize chunksize; 

    std::string str = 
     "POST /test/upload.php HTTP/1.1\r\n" 
     "Host: site.net\r\n" 
     "User-Agent: User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36\r\n" 
     "Connection: Keep-alive\r\n" 
     "Content-Type: multipart/form-data; boundary=----WebKitFormBoundarym9PgiUg6fjxm2Hpr\r\n" 
     "\r\n" 
     "------WebKitFormBoundarym9PgiUg6fjxm2Hpr\r\n" 
     "Content-Disposition: form-data; name=\"tmp\"; filename=\"photo.jpg\"\r\n" 
     "Content-Type: image/jpeg\r\n" 
     "\r\n"; 

    // send str ... 

    do 
    { 
     chunksize = File.readsome(chunk, sizeof(chunk)); 
     if (chunksize < 1) 
      break; 

     // send chunk up to chunksize bytes ... 
    } 
    while (true); 

    File.close(); 

    str = 
     "\r\n" 
     "------WebKitFormBoundarym9PgiUg6fjxm2Hpr--\r\n"; 

    // send str ... 
+0

我認爲你的權利這個版本更好,我會嘗試,但我可以發幾次這樣的查詢? – user2417534

+0

是的。與UDP不同,TCP是一個字節流。您不必在單個send()調用中發送所有內容。你可以使用多個send()調用。 –