将图像保存到数据库并从服务器加载

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 由静态分析器生成的警告。分析器是识别编程错误的非常有用的工具,因此请充分利用这个出色的工具。

    1234563 .

    一旦您将从sqlite3_column_text 获得的const char * 转换为NSString,然后您想要获取该字符串并创建一个URL,例如:

    NSURL *url = [NSURL URLWithString:urlStringFromDatabase];
    

    然后,您可以将 NSURLUIImageView 类别(如 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加载

将 JSON 保存到 NSUserDefaults 并从那里填充ableview 是真的吗?

将画布图像保存到主机服务器

如何显示缓冲图像