I added many JPEG images into an Access DB as Long binary data. Now I want to retrieve these images into a TImage
using Delphi code.
For this work, I wrote the code below, but after running it gives me a JPEG error #53 error. I searched in Google for this error code, and tried some solutions, such as saving as picture to new JPG format, but that does not change anything.
Also, I found different codes for retrieving an image from a database, but all of them gave me the same JPEG error #53 error.
Where is the problem?
procedure RetrieveImage;
var
Jpg : TGraphic;
Stream: TStream;
query : string;
Field: TBlobField;
Begin
Stream := nil;
Jpg := nil;
query := 'Select JPGFile From Table Where Name=' QuotedStr(SoftName);
Try
With ADOQuery do
Begin
Try
SQL.Clear;
SQL.Add(query);
Open;
Field := TBlobField(FieldbyName('JPGFile'));
Stream := CreateBlobStream(Field,bmRead);
Jpg := TJpegImage.Create;
Jpg.LoadFromStream(Stream);
MainForm.PictureBox.Picture.Graphic:= Jpg;
Finally
Close;
End;
End;
Finally
Stream.Free;
Jpg.Free;
End;
End;
EDIT:
I used C# code for insert a JPG file into the database (the following code is simplified):
// Insert Data to Access tables
private void InsertToTable(string connectionString, string query)
{
using (OleDbConnection connection = new OleDbConnection(connectionString))
{
try
{
connection.Close();
using (OleDbCommand command = new OleDbCommand(query, connection))
{
connection.Open();
using (OleDbDataReader reader = command.ExecuteReader())
{
reader.Close();
}
command.Cancel();
}
connection.Close();
}
finally
{
connection.Close();
}
}
}
// Insert Image into database
private void SaveToDataBase(string jpegPath)
{
//jpegPath example is: (C:\Image\1.jpg)
string FilePath = Application.StartupPath directory dbName;
string MDBConnStr = "Provider=Microsoft.Jet.OLEDB.4.0;" "Data Source=" FilePath "; Jet OLEDB:Engine Type=5";
// Convert Image to binary
var image = File.ReadAllBytes(jpegPath);
InsertToTable(MDBConnStr, $"INSERT INTO Table JPGFile VALUES('{image}')");
}
CodePudding user response:
In your C# code, why are you using ExecuteReader()
to execute an INSERT
statement? You should be using ExecuteNonQuery()
instead.
More importantly, you are not actually inserting the contents of your image
byte array into the database, which is why Delphi's TJPEGImage
is failing to load the data later. Your SQL query is being created as an interpolated string, but your {image}
expression does not insert the raw bytes into the query, like you think it does. And even if it did, that is not the correct way to insert raw bytes into a "Long Binary" field to begin with.
You need to use a parameterized query instead. Add an OleDbParameter
to the command.Parameters
collection to pass the image
data into the database, where you set its DbType
property to Binary
, its OleDbType
property to either Binary
,LongVarBinary
, or VarBinary
, and its Value
property to your image
byte array. You can then refer to that parameter in your SQL statement.
See Configuring parameters and parameter data types, especially the section on Using parameters with an OleDbCommand or OdbcCommand.
Try something more like this:
// Insert Image into database
private void SaveToDataBase(string jpegPath)
{
//jpegPath example is: (C:\Image\1.jpg)
// Convert Image to binary
var image = File.ReadAllBytes(jpegPath);
string FilePath = Application.StartupPath directory dbName;
string MDBConnStr = "Provider=Microsoft.Jet.OLEDB.4.0;" "Data Source=" FilePath "; Jet OLEDB:Engine Type=5";
using (OleDbConnection connection = new OleDbConnection(MDBConnStr))
{
connection.Open();
using (OleDbCommand command = new OleDbCommand("INSERT INTO Table JPGFile VALUES(?)", connection))
{
command.Parameters.Add("@Image", OleDbType.LongVarBinary).Value = image;
command.ExecuteNonQuery();
}
}
}
Note, however, that binary parameters in OLEDB are limited to 8000 bytes max.