【问题标题】:A C cgi script to serve binary file from sqlite3_column_blob pointer从 sqlite3_column_blob 指针提供二进制文件的 C cgi 脚本
【发布时间】:2015-08-22 22:18:45
【问题描述】:

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

【问题讨论】:

  • 你知道你的blob字段的真实格式吗?因此,您可以将数据转换为所需的结构并发送/显示您想要的内容。
  • 您好! BLOB 数据是 jpeg 图像,因此我需要将这些字节输出到客户端,而无需将标头设置为 image/jpeg。
  • 你的客户是什么?一个简单的接口,一个socket连接的东西……
  • 应该是APACHE下的c cgi脚本

标签: c sqlite cgi blob


【解决方案1】:

好的,感谢大家的支持。在我正在寻找的代码下方,只需将“sqlite3_column_blob”发送到标准输出...简单!

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

【讨论】:

    【解决方案2】:

    Common Gateway Interface 是一种较旧形式的 Web 服务器接口(请参阅此处的 W3 页面http://www.w3.org/CGI/),根据我的记忆,Web 服务器将套接字传递给 CGI 应用程序,该应用程序作为子进程启动,我认为两者都是 STDIN和标准输出。 CGI 应用程序负责所有 HTTP 标头和所有其余内容管理。

    因此,您的应用程序需要做的是创建必要的 HTTP 标头指令来指示内容类型和其他部分,然后将内容字节作为正文发送。

    我要问的一个问题是,为什么在 C 中这样做,而不是在其他一些语言(例如 Perl 或 Php)中对这类事情有很好的支持?

    第一步是获取并处理请求头数据。这可能因特定的 Web 服务器及其使用的 CGI 功能而异。过去似乎只是从 STDIN 读取处理 HTTP 请求标头的问题,一次一个回车分隔行,直到找到一个空行。但是,您的特定 Web 服务器可能会提供不同的机制。

    HTTP 响应标头信息通常是相当标准的,除了内容长度之外,其中大部分不会发生变化,内容长度会因图像大小而变化,因此向下发送的字节数。我很确定在过去我实际上忽略了 content-length HTTP 响应指令,因为向下发送数据然后关闭 socked 表示内容下载已完成。

    如果您阅读IETF RFC 3875 Common Gateway Interface,您会看到很多“系统定义”的漏洞,因此您需要做什么取决于您的网络服务器。

    这是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 的答案,其中提到了一些可能有用的库。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-24
      相关资源
      最近更新 更多