将数据库中的所有图像 (BLOB) 保存到文件夹(“内存不足。”)

Posted

技术标签:

【中文标题】将数据库中的所有图像 (BLOB) 保存到文件夹(“内存不足。”)【英文标题】:Save all images (BLOB) from database to folder ('Out of memory.') 【发布时间】:2021-11-13 04:15:58 【问题描述】:

我有一个 SQLite 数据库,其中一个表有很多图像,并且我在数据库大小方面遇到了一些问题,所以我转换了逻辑以将图像存储在一个文件夹中并检索所需的图像,所以我是现在正在尝试获取存储在数据库中的所有图像并将其保存在文件夹中,但我收到错误Out of memory

注意:我在将图像插入数据库之前使用压缩方法压缩图像,并在检索图像时使用解压缩方法。

这是我的代码:

protected void Save()
    
        try
        
            using (SQLiteDataReader reader = DBConn.ExecuteReader("Select ID,image from transfers", CommandType.Text))
            
                while (reader.Read())
                
                    if (reader["image"] != DBNull.Value)
                    
                        byte[] image = (byte[])reader["image"];
                        image = Decompress(image);
                        Image newImage = byteArrayToImage(image);

                        string path = string.Format(@"E:\images\CI-0.Jpeg", reader["ID"].ToString());
                        newImage.Save(path, ImageFormat.Jpeg);
                    
                
            
            MessageBox.Show("done");
        
        catch (SQLiteException ex)
        
            // Do some logging or something. 
            MessageBox.Show("There was an error accessing your data. DETAIL: " + ex.Message);
        
    

从字节中获取图像的方法

public Image byteArrayToImage(byte[] bytesArr)
    
        Bitmap newBitmap;
        using (MemoryStream memoryStream = new MemoryStream(bytesArr))
        
            using (Image newImage = Image.FromStream(memoryStream))
            
                newBitmap = new Bitmap(newImage);
            
        
        return newBitmap;

        // I tried this code also.
        //return (Bitmap)((new ImageConverter()).ConvertFrom(bytesArr));
    

这就是解压方法

public static byte[] Decompress(byte[] data)
    
        using (MemoryStream input = new MemoryStream(data))
        using (MemoryStream output = new MemoryStream())
        
            using (DeflateStream dstream = new DeflateStream(input, CompressionMode.Decompress))
            
                dstream.CopyTo(output);
            
            return output.ToArray();
        
    

【问题讨论】:

为什么不直接保存字节呢?为什么将其加载到图像中然后保存图像? (这一切我 如果您在***代码块中正确处理 newImage 会发生什么:using (Image newImage = byteArrayToImage(image)) /* get path & save image */ 压缩图像没有意义:除非您使用 BMP 或 SVG 格式,否则 JPEG 和 PNG 图像已经被压缩。如前所述,只需获取字节并使用File.WriteAllBytes() 将字节保存到磁盘。我假设您还存储了原始图像格式或文件扩展名。请勿使用怪异的方法更改图像格式以将其保存到光盘。 @Jimi,是的,你是对的,这是一个旧项目,我不知道当我这样做的时候,现在如果我不使用解压缩方法,图像将被保存,但我无法打开它。我使用了File.WriteAllBytes() 并且我能够保存前 63 张图像然后它崩溃了,解压缩方法中的问题“内存不足” @CaiusJard,是的,现在我直接写到路径,谢谢 【参考方案1】:

我根据从 cmets 获得的建议更改了代码,所以谢谢。

这是最终代码:

 protected void Save()
    
        try
        
            using (SQLiteDataReader reader = DBConn.ExecuteReader("Select ID,image from transfers", CommandType.Text))
            
                while (reader.Read())
                
                    if (reader["image"] != DBNull.Value)
                    
                        byte[] image = (byte[])reader["image"];
                        image = Decompress(image);

                        string path = string.Format(@"E:\images\CI-0.jpeg", reader["ID"].ToString());
                        File.WriteAllBytes(path, image);
                    
                
            
            MessageBox.Show("done");
        
        catch (SQLiteException ex)
        
            // Do some logging or something. 
            MessageBox.Show("There was an error accessing your data. DETAIL: " + ex.Message);
        
    

我把解压方法改成如下:

    public static byte[] Decompress(byte[] inputData)
    
        if (inputData == null)
            throw new ArgumentNullException("inputData must be non-null");

        MemoryStream input = new MemoryStream(inputData);
        MemoryStream output = new MemoryStream();
        using (DeflateStream dstream = new DeflateStream(input, CompressionMode.Decompress))
        
            dstream.CopyTo(output);
        
        return output.ToArray();

        if (inputData == null)
            throw new ArgumentNullException("inputData must be non-null");
    

【讨论】:

以上是关于将数据库中的所有图像 (BLOB) 保存到文件夹(“内存不足。”)的主要内容,如果未能解决你的问题,请参考以下文章

优化数据库中的 MySQL 文件 (blob)

将 blob 从 JS 保存到 Oracle SQL?

将 javascript 图像 blob 保存到 ASP.NET Core 控制器

如何使用 SQLite 和 PHP 将图像保存到数据库?

如何将图像转换为 Base64 字符串,并转换回图像,保存到 azure blob

将图像从 url 直接上传到数据库 blob 字段