0

5 years ago I had a Visual Basic program that could save images into a MySQL database and retrieve it later. It all worked. When COVID struck this project was canned. Now they want it back...

I've got an SQL backup file of the entire database that I restored to the new server. All information restored fine, except the image data, which was stored as Long Blob.

The funny thing is, if I try to open the original database image it does not work, but if I update the same record, with the original image I used 5 years back, it works!!!

None of the code have changed. After several days searching online, I think I've narrowed it down to what seems to be database character set and collation.

I used a hex editor to see the differences between the restored file data in the database and the newly saved data: Hex edit of two files

The top file is the newly uploaded image and the bottom is from the backup. You can clearly see both files are jpeg images from the "JFIF" in the first line. The newly saved file data starts with "FF D8 FF E0", recognized by Wikipedia as a Jpeg file signature. However, the restored data starts with "C3 BF C3 98 C3 BF C3 A0" which is not any recognized file signature Google can find.

I even managed to open the Backup SQL file to see what is supposed to be restored, and the image data starts with "FF D8 FF E0"!!! Why would SQL restore 4 byte "FF D8 FF E0" binary data as 8 bytes ("C3 BF C3 98 C3 BF C3 A0")?

I tried restoring the database with different character sets but without success.

Would it matter if the new Mysql installation is on a 64bit computer and the backup comes from a 32 bit PC?

Also my def PC have changed from win 7 32bit to a win 10 64bit PC.

The only viable solution currently is to re-upload all the pictures to the database, if I can still find them all, but there are thousands of product pictures that needs to be redone. A database solution would be quickest.

It is probably just an restore setting in MySQL but the answer has so far eluded me.

Any suggestions?

Edit: Here's the header on the backup file:

CREATE DATABASE  IF NOT EXISTS `xxxx_planner` /*!40100
DEFAULT CHARACTER SET latin1 */;
USE `xxxx_planner`;
-- MySQL dump 10.13  Distrib 5.7.17, for Win64 (x86_64)
--
-- Host: xxx.xxx.xx.xx    Database: xxxx_planner
-- ------------------------------------------------------
-- Server version   5.7.19

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT   */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

Edit 2: Heres the functions to store and retrieve that data:

Public Function updateMapData(sName As String, iID As Int16, iHeight As Int16, iWidth As Int16, iImg As Image)
    Dim arrImage() As Byte

    Dim Sql As String
    Try

        Dim mstream As New System.IO.MemoryStream()
        iImg.Save(mstream, System.Drawing.Imaging.ImageFormat.Jpeg)
        arrImage = mstream.GetBuffer()

        mstream.Close()
        Sql = "UPDATE maps SET Map_Data =  @studimg, Map_Name = @MNAME, Height =  @HEIGHT, Width =  @WIDTH WHERE id = @iID"

        ' Sql = "INSERT INTO maps(Map_Name, Store, Height, Width, Map_Data) VALUES (@MNAME, @STORE, @HEIGHT, @WIDTH, @studimg)"
        Using cmd As New MySqlCommand
            cmd.Connection = MySqlConn
            cmd.CommandText = Sql
            cmd.Parameters.AddWithValue("@MNAME", sName)
            cmd.Parameters.AddWithValue("@iID", iID)
            cmd.Parameters.AddWithValue("@HEIGHT", iHeight)
            cmd.Parameters.AddWithValue("@WIDTH", iWidth)
            cmd.Parameters.AddWithValue("@studimg", arrImage)
            Dim r As Integer
            r = cmd.ExecuteNonQuery()
            If r > 0 Then
                MsgBox("Record hass been Saved!")
            Else
                MsgBox("No record has been saved!")
            End If
            cmd.Parameters.Clear()
        End Using


    Catch ex As Exception
        MessageBox.Show(ex.Message)
    End Try


    Return 0
End Function
Public Function getMapData(iID As Integer) As Image
    Dim sql As String
    Dim dbPic As Image

    sql = "SELECT Map_Data FROM maps WHERE id=" & iID

    RefreshMySQLConnectionState()
    Using cmd As New MySqlCommand(sql, MySqlConn)
        Using sqlReader As MySqlDataReader = cmd.ExecuteReader()
            sqlReader.Read()
            Dim arrImage As Byte()
            Try
                arrImage = sqlReader("Map_Data")

                'This just writes the data to file for troubleshooting
                Dim filename As String
                filename = iID & "-" & DateTime.Now.ToString("dd HHmmss") & ".blob"
                File.WriteAllBytes(filename, arrImage)

                If Not arrImage.Length = 0 Then
                    '' Dim mstream As New System.IO.MemoryStream(arrImage)
                    '' dbPic = Image.FromStream(mstream)
                    'Dim imageConverter As ImageConverter = New System.Drawing.ImageConverter()
                    ' dbPic = TryCast(ImageConverter.ConvertFrom(arrImage), Image)
                    Dim mstream As New IO.MemoryStream(CType(arrImage, Byte()))
                    mstream.Position = 0 'added recently as part of posible solutions...
                    dbPic = System.Drawing.Image.FromStream(mstream) ' Error happens here...

                Else
                    dbPic = Nothing
                End If

            Catch ex As Exception
                dbPic = Nothing   'ERROR: Parameter is not valid.
            End Try

        End Using
    End Using

    Return dbPic

End Function
Richard
  • 1
  • 1
  • `5 years ago` - was it https://stackoverflow.com/q/50467582/11683? – GSerg Aug 19 '22 at 13:35
  • What kind of backup was that, and how did you take it? – GSerg Aug 19 '22 at 13:46
  • Yes, same project but different issue. That was a website allowing users to update pictures through a browser. This part is all Visual Basic Uploading. can post the code if you like. – Richard Aug 19 '22 at 13:55
  • For what it's worth, `C3 BF C3 98 C3 BF C3 A0` [is UTF-8 representation](https://dotnetfiddle.net/2I2sAR) of the `ÿØÿà` (`FF D8 FF E0`). When taking and/or restoring backups, you messed up the UTF8/ASCII encoding. Which should have not been an issue at all because the field, as you are saying, is binary rather than textual. Hence the question how you took the backup and restored it. – GSerg Aug 19 '22 at 13:56
  • Backup was done through MySQL Workbench single file saved as .sql. – Richard Aug 19 '22 at 13:56
  • Thanks GSerg, You confirmed my suspicions. Can it be fixed? Either during restoration or after through an SQL query? – Richard Aug 19 '22 at 13:58
  • What bytes do you have in the backup file? – GSerg Aug 19 '22 at 14:01
  • Backup file was 2.9G! took a while to get the statement: INSERT INTO `maps` VALUES (8,'002 1st Fl','002',1500,4050,'ÿ\Øÿ\à\0JFIF\0\0`\0`\0\0ÿ\Û\0C\0. Backup seem to have correct data. – Richard Aug 19 '22 at 14:16
  • Those are not the bytes, they are characters, as shown by whatever viewer you are using to view it. What are the file bytes corresponding to the `'ÿ\Øÿ\à\0JFIF\0\0\0\0\0ÿ\Û\0C\0` part? – GSerg Aug 19 '22 at 14:18
  • Sorry: Here's the hex editor output: FF 5C D8 FF 5C E0 5C 30 10 4A 46 49 46 5C 30 01 01 01 5C 30 for the values: ÿ\Øÿ\à\0JFIF\0\0 – Richard Aug 19 '22 at 14:30
  • So apparently the backup saved in Windows-1252. So load it as such. – GSerg Aug 19 '22 at 14:38
  • According to this article: https://stackoverflow.com/questions/1607408/find-a-windows-1252-char-in-mysql-column latin1 is cp1252 is windows-1252. Both the restored database and table has default set to latin1. The SQL backup file also states: /*!40100 DEFAULT CHARACTER SET latin1 */. What else am I missing? Oh, and the import file shows old MySQL using MyISAM, but the new MySQL database using MariaDB. Looks like I'll have to import all the pictures again. will take a bit of time but this problem cost me three days already. Bring the coffee!! – Richard Aug 20 '22 at 09:22
  • I am talking about the encoding in which the backup file, being a [simple text file](https://www.joelonsoftware.com/articles/Unicode.html), is. Not about the encoding that it instructs the database to use in the created tables. – GSerg Aug 20 '22 at 09:28

0 Answers0