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