一个C cgi脚本,用于从sqlite3_column_blob指针提供二进制文件

时间:2015-06-08 12:34:25

标签: c sqlite cgi blob

我从sqlite数据库中检索了二进制数据,现在我有了指向二进制数据的指针(sqlite3_column_blob)。如何使用C cgi脚本将此数据输出到客户端?

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);

2 个答案:

答案 0 :(得分: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,您会看到很多&#34;系统定义&#34;漏洞太多,你需要做的将取决于你的网络服务器。

这是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 :(得分:1)

好的,感谢大家的支持。在我正在寻找的代码下面,只需发送&#34; sqlite3_column_blob&#34; stdout ......很简单!

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;
}