将图像保存到数据库并从服务器加载
Posted
技术标签:
【中文标题】将图像保存到数据库并从服务器加载【英文标题】:Save image to database and load from server 【发布时间】:2013-08-22 09:16:40 【问题描述】:我将图像存储在服务器中。然后我获取图像并通过图像 URL 保存到 db1.sqlite 文件。图像保存到 db1.sqlite 文件,如 URL。如何显示保存的 URL 中的图像。 product_image 具有 imageURL 路径。
代码:
sqlite 表结构:
CREATE TABLE "product" ("id" INTEGER PRIMARY KEY NOT NULL , "cat_id" INTEGER NOT NULL , "product_image" VARCHAR NOT NULL , "order_by" INTEGER NOT NULL )
插入代码:
const char *sqlInsert = [[NSString stringWithFormat:@"insert into product (id, cat_id,product_image,order_by) values ('%@','%@','%@','%@')", [tuser objectForKey:@"id"], [tuser objectForKey:@"cat_id"],[tuser objectForKey:@"product_image"],[tuser objectForKey:@"order_by"]] cStringUsingEncoding:NSUTF8StringEncoding];
NSLog(@"product insert %s", sqlInsert);
if(sqlite3_prepare_v2(database, sqlInsert, -1, &addStmt, NULL) != SQLITE_OK)
NSAssert1(0, @"Error while creating add statement. '%s'", sqlite3_errmsg(database));
if(SQLITE_DONE != sqlite3_step(addStmt))
NSAssert1(0, @"Error while inserting data. '%s'", sqlite3_errmsg(database));
图片抓取:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
//NSLog(@"docs dir is %@", documentsDirectory);
NSString *path = [documentsDirectory stringByAppendingPathComponent:@"db1.sqlite"];
//NSLog(@"filepath %@",path);
mArray = [[NSMutableArray alloc]init];
if (sqlite3_open([path UTF8String], &database) == SQLITE_OK)
const char *sql = "SELECT id,cat_id,product_image FROM product order by order_by";
NSLog(@"sql is %s",sql);
sqlite3_stmt *statement;
// int catID = 0;
if (sqlite3_prepare_v2(database, sql, -1, &statement, NULL) == SQLITE_OK)
// We "step" through the results - once for each row.
while (sqlite3_step(statement) == SQLITE_ROW)
int length = sqlite3_column_bytes(statement, 2);
NSData *imageData = [NSData dataWithBytes:sqlite3_column_blob(statement, 2) length:length];
UIImage *image = [UIImage imageWithData:imageData];
[mArray addObject:image];
[image release];
sqlite3_finalize(statement);
else
sqlite3_close(database);
NSAssert1(0, @"Failed to open database with message '%s'.", sqlite3_errmsg(database));
// Additional error handling, as appropriate...
【问题讨论】:
【参考方案1】:和你离线聊天,发现product_image
不是NSData
。 (我后来错误地从sqlite3_column_blob
的存在推断出您正在尝试存储二进制数据,但事实并非如此。)显然product_image
是包含URL 的字符串。所以将其存储为字符串。并且永远不要在你的 SQL 语句中使用stringWithFormat
,而是使用带有?
占位符的sqlite3_bind_xxx
函数,例如:
const char *sqlInsert = "insert into product (id, cat_id, product_image, order_by) values (?, ?, ?, ?)";
if (sqlite3_prepare_v2(database, sqlInsert, -1, &addStmt, NULL) != SQLITE_OK)
NSAssert1(0, @"Error while creating add statement. '%s'", sqlite3_errmsg(database));
if (sqlite3_bind_int(addStmt, 1, [[tuser objectForKey:@"id"] intValue]) != SQLITE_OK)
NSAssert1(0, @"Error binding 1. '%s'", sqlite3_errmsg(database));
if (sqlite3_bind_int(addStmt, 2, [[tuser objectForKey:@"cat_id"] intValue]) != SQLITE_OK)
NSAssert1(0, @"Error binding 2. '%s'", sqlite3_errmsg(database));
if (sqlite3_bind_text(addStmt, 3, [[tuser objectForKey:@"product_image"] UTF8String], -1, NULL) != SQLITE_OK)
NSAssert1(0, @"Error binding 3. '%s'", sqlite3_errmsg(database));
if (sqlite3_bind_int(addStmt, 4, [[tuser objectForKey:@"order_by"] intValue]) != SQLITE_OK)
NSAssert1(0, @"Error binding 4. '%s'", sqlite3_errmsg(database));
if (SQLITE_DONE != sqlite3_step(addStmt))
NSAssert1(0, @"Error while inserting data. '%s'", sqlite3_errmsg(database));
// don't forget to finalize
sqlite3_finalize(addStmt);
如果您这样做,您也必须更改检索图像的代码。例如,您有:
while (sqlite3_step(statement) == SQLITE_ROW)
int length = sqlite3_column_bytes(statement, 2);
NSData *imageData = [NSData dataWithBytes:sqlite3_column_blob(statement, 2) length:length];
UIImage *image = [UIImage imageWithData:imageData];
[mArray addObject:image];
[image release];
一些想法:
[image release]
是过度发布。 imageWithData
返回一个 autorelease
对象,因此您不需要/不想释放它。这种错误可能是灾难性的,因此我建议您通过静态分析器运行代码以帮助识别这些错误(通过从“产品”菜单中选择“分析”,或按 command+shift+B)。您应该有 zero 由静态分析器生成的警告。分析器是识别编程错误的非常有用的工具,因此请充分利用这个出色的工具。
一旦您将从sqlite3_column_text
获得的const char *
转换为NSString
,然后您想要获取该字符串并创建一个URL,例如:
NSURL *url = [NSURL URLWithString:urlStringFromDatabase];
然后,您可以将 NSURL
与 UIImageView
类别(如 SDWebImage
)结合使用,以异步检索图像(并执行所有适当的缓存等)。
[imageView setImageWithURL:url
placeholderImage:[UIImage imageNamed:@"placeholder.png"]];
而且,冒着重蹈覆辙的风险,您的图像检索代码会检查 SQLite 函数是否返回,例如 SQLITE_OK
,但如果没有,则不会显示 sqlite3_errmsg
。调试应用程序时,请务必查看此内容。它将为您节省数小时的开发/调试时间。
【讨论】:
我应该在“product_image”中使用什么 VARCHAR NOT NULL?创建表时 BLOB 或 VarChar。 1.由于product_image
是一个包含图像URL 的字符串,因此您应该使用TEXT
来定义列,而不是BLOB
。 2.不,您的图像获取代码不正确。请参阅我修改后的答案。以上是关于将图像保存到数据库并从服务器加载的主要内容,如果未能解决你的问题,请参考以下文章
将抽象数据类型保存和加载到 json 文件并从游戏中的文件中读取 Haskell
VB - 连接到本地 SQL 服务器并从 excel 将数据加载到表中
将UIColor保存到NSUserDefaults并从NSUserDefaults加载