2014-01-21 51 views
0

我想連接一些字符串和一個jpeg二進制文件的內容,以在LINUX下C發出一個http post請求。如果我使用正常的字符串操作,jpeg中的二進制內容一旦遇到0x00就會被終止。 (例如,如果我的HEX二進制文件爲FF D8 FF C0 00 11 08 ...),在concat之後,二進制部分將以FF D8 FF C0結束。concat字符串與二進制:二進制內容被截斷時,命中0x00

有誰知道如何解決這個問題?語言是C.謝謝

fp = fopen(filename, "rb") 
fseek(fp, 0, SEEK_END); 
fileLen = ftell(fp); 
fseek(fp, 0, SEEK_SET); 
buffer = (char *)malloc(fileLen); 
fread(buffer, fileLen, 1, fp); 

//now buffer has the content of the JPEG image 

//next combine both string and binary together to make a http post request 

snprintf(poststr, MAXSUB, 
      "--%s\r\nContent-Disposition: form-data;" 
      "name=\"datafile\"; filename=\"%s\"\r\nContent-Type: image/jpeg\r\n\r\n" 
      "%s\r\n" 
      "--%s\r\n" 
      "Content-Disposition: form-data; name=\"boxkey\"\r\n\r\n%s\r\n" 
      "--%s--", boundary, filename, buffer, boundary, key, boundary); 

回答

2

這裏是你的問題和從我這裏提示,讓我們看看他們兩個。

複製二進制數據

A C字符串以0終止,所以如果用格式說明%s打印,並通過一個(二進制)串嵌入0,第一個將被識別爲字符串終止子。

取而代之,請使用memcpy,以便您可以明確傳遞尺寸。 假設的poststr規模大到足以容納一切,你應該做的:

int headLength = snprintf(poststr, MAXSUB, 
     "--%s\r\nContent-Disposition: form-data;" 
     "name=\"datafile\"; filename=\"%s\"\r\nContent-Type: image/jpeg\r\n\r\n" 
    boundary, filename 
); 

// Declarations added for clarity, you can remove them 
char *bodystr = poststr + headLength; 
char *footerstr = bodystr + bufferLength; 

// Copy binary here 
memcpy(bodystr, buffer, bufferLength); 

snprintf(footerstr, MAXSUB, 
     "--%s\r\n" 
     "Content-Disposition: form-data; name=\"boxkey\"\r\n\r\n%s\r\n" 
     "--%s--", boundary, key, boundary 
); 

請考慮結果字符串將有嵌入0,所以你將不得不計算出「真實」的長度並將其保存在某處(strlen也會在第一個嵌入的0處停止)。

編碼MIME /多部分消息

我看到你正在建設一個多HTTP請求二進制數據。 您可以對二進制數據進行編碼,主要以BASE64或quoted-printable進行編碼。有兩個C庫,但您也可以在50-60行代碼中實現相同的功能。您將必須指定您在標題中使用的編碼。有關語法參考,請參閱RFC 2045 §6.1

在這種情況下,您的代碼將工作,因爲數據將編碼爲ASCII字符串。

+0

嗨,感謝您的快速和乾淨的答覆!我是否必須對二進制部分進行編碼才能使其工作?或者我可以讓它們保持原樣。 –

+0

我建議編碼,它將確保任何客戶端/服務器可以處理您的消息,而不會因爲編碼或其他問題而破壞它。您的消息將是純ASCII。此外,使用Base64進行編碼,因爲它比quoted-printable更緊湊。 –

+0

嗯,如果我使用Based64編碼我的二進制部分,我在哪裏解碼它或者服務器會爲我解碼? –

0

如果要將二進制數據附加到字符串上,請找到終止位置NULL,然後將二進制數據memcpy寫入其中。例如:然而

void 
appendBinaryToString (char *string, void *binary, size_t length) 
{ 
    /* IMPORTANT 
    * Ensure the memory allocated for string has sufficient space 
    * to permit the binary to be copied in 
    */ 

    /* Offset of NULL is at strlen(string) */ 
    memcpy (string + strlen(string), binary, length; 
} 

注意,輸出將是長度length + strlen(string)而不是零終止的字符串的二進制字符數組。那真的是你想要的嗎?如果是這樣,你可能會更好地考慮這個問題:'我如何複製字符串的二進制內容,並將另一個二進制blob複製到相鄰的內存位置?'。我提到這個的原因是,我認爲你正試圖將二進制數據複製到poststr,然後將其視爲一個字符串;也許你真的想編碼的數據(base64或類似的),然後加上;由於編碼數據不包含NUL字節,因此您不會遇到問題。

根據你用來做這篇文章的庫,你可能會發現它爲你做了很多努力。

相關問題