2015-06-08 32 views
1

我從sqlite數據庫檢索二進制數據,現在我有二進制數據指針(sqlite3_column_blob)。如何用C cgi腳本將這些數據輸出到客戶端?C cgi腳本從sqlite3_column_blob服務二進制文件指針

char *sql = "SELECT Data FROM Images WHERE Id = 1"; 

sqlite3_stmt *pStmt; 
rc = sqlite3_prepare_v2(db, sql, -1, &pStmt, 0); 

if (rc != SQLITE_OK) { 

    fprintf(stderr, "Failed to prepare statement\n"); 
    fprintf(stderr, "Cannot open database: %s\n", sqlite3_errmsg(db)); 

    sqlite3_close(db); 

    return 1; 
} 

rc = sqlite3_step(pStmt); 

int bytes = 0; 

if (rc == SQLITE_ROW) { 

    bytes = sqlite3_column_bytes(pStmt, 0); 
} 
// >>>>next row is function to save file but I want output binary data to client<<<< 
fwrite(sqlite3_column_blob(pStmt, 0), bytes, 1, fp); 
+0

你知道blob字段的真實格式嗎?因此,您可以將數據轉換爲預期結構併發送/顯示您想要的內容。 – LPs

+0

你好! BLOB數據是一個jpeg圖像,所以我需要輸出到客戶端這些字節沒有轉換設置標題爲圖像/ jpeg。 –

+0

你的客戶是什麼?一個簡單的接口,東西套接字連接... – LPs

回答

1

通用網關接口是Web服務器接口的舊形式(見W3頁面在這裏http://www.w3.org/CGI/),並從我的記憶中的Web服務器通過套接字相應地開始爲孩子過程中,我覺得作爲CGI應用程序STDIN和STDOUT。 CGI應用程序負責所有HTTP標題和所有其他內容管理。

因此,您的應用程序需要做的是創建必要的HTTP標頭指令來指示內容類型和其他片段,然後將內容字節作爲主體發送。

我想問的一個問題是,爲什麼在C語言和其他語言如Perl或Php中對此類事物有很好的支持?

第一步是獲取並處理請求頭數據。這可能會有所不同,具體取決於特定的Web服務器和它使用的CGI功能。在過去,它似乎只是從STDIN中讀取處理HTTP請求頭的信息,一次回車分隔線,直到找到空行。但是,您的特定Web服務器可能會提供不同的機制。

HTTP響應標頭信息通常是相當標準的,其中的大部分內容不會因圖像大小而異,因此發送的字節數減少。我非常肯定的是,在過去,我實際上已經忽略了內容長度的HTTP響應指令,因爲發送數據,然後關閉socked指示內容下載完成。

如果您閱讀了IETF RFC 3875 Common Gateway Interface,您會看到很多「系統定義」的漏洞,您需要做的事情取決於您的Web服務器。

這裏是一個How To for CGI programming with Apache web server

這篇文章W3 HTTP Header Field Definitions提供了有關各種標題指令的信息。

W3 Content-type header field提供了有關內容類型指令的信息。

這是一個O'Reilly open book on CGI Programming提供基本面的概述,但它看起來有點舊。

另請參考CGI上此stack overflow CGI c file open的回答,其中提到了一些可能有用的庫。

1

好的,感謝所有的支持。在我正在尋找的代碼下面,只需發送「sqlite3_column_blob」到stdout ... easy!

int main(void) { 
    sqlite3 *db; 
    char *err_msg = 0; 
    int rc = sqlite3_open("./test.db", &db); 
    if (rc != SQLITE_OK) { 
     // error opening the SQLite database, send an error message to 
     // requesting application as plain text. 
     fprintf(stdout, "%s", "Content-Type: text/plain;\n\n"); 
     fprintf(stdout, "Cannot open database: %s\n", sqlite3_errmsg(db)); 
     sqlite3_close(db); 
     return 1; 
    } 

    char *sql = "SELECT Data FROM Images WHERE Id = 1"; 
    sqlite3_stmt *pStmt; 
    rc = sqlite3_prepare_v2(db, sql, -1, &pStmt, 0); 
    if (rc != SQLITE_OK) { 
     // error with SQLite retrieving data, send an error message to 
     // requesting application as plain text. 
     fprintf(stdout, "%s", "Content-Type: text/plain;\n\n"); 
     fprintf(stdout, "Failed to prepare statement\n"); 
     fprintf(stdout, "Database error: %s\n", sqlite3_errmsg(db)); 
     sqlite3_close(db); 
     return 1; 
    } 

    rc = sqlite3_step(pStmt); 
    int bytes = 0; 
    if (rc == SQLITE_ROW) { 
     // send the content type HTTP response directive to requesting 
     // application. the SQLite BLOB contains JPEG image data. 
     fprintf(stdout, "%s", "Content-Type: image/jpeg;\n\n"); 
     bytes = sqlite3_column_bytes(pStmt, 0); 
    } 

    bytes = sqlite3_column_bytes(pStmt, 0); 
    // send the image data from the SQLite BLOB to the requesting application 
    fwrite(sqlite3_column_blob(pStmt, 0), bytes, 1, stdout); 

    // cleanup and close SQLite connection and exit 
    rc = sqlite3_finalize(pStmt); 
    sqlite3_close(db); 

    return 0; 
}