I have a Stored Procedure that takes blob data (VarBinary) as a parameter I can't get it to work with TADOStoredProc though.
The Stored Procedure
ALTER PROCEDURE [dbo].[spAddToSolve] #SolveData VarBinary(max)
AS
BEGIN
INSERT INTO dbo.ToSolve (Data, SolveStatus)
VALUES (#SolveData, 0)
END
Here are the two things I tried.
This first one fails finding the Field, what am I Missing
procedure AddItem(dbCon : TADOConnection; sourcePath : String);
var
addProc : TADOStoredProc;
field : TField;
dataStream : TFileStream;
blobStream : TStream;
begin
if FileExists(sourcePath) then
begin
dataStream := TFileStream.Create(sourcePath, fmOpenREad or fmShareDenyNone);
try
addProc := TADOStoredProc.Create(nil);
addProc.Connection := dbCon;
addProc.ProcedureName := 'spAddToSolve';
field := addProc.FieldByName('#SolveData'); //Field'#SolveData' not found
blobStream := addProc.CreateBlobStream(field, bmWrite);
blobStream.CopyFrom(dataStream, dataStream.Size);
addProc.Open;
finally
addProc.Free();
dataStream.Free();
end;
end;
end;
Not sure how to get the method to work, I don't know how to get the stream data into the param value.
procedure AddItem(dbCon : TADOConnection; sourcePath : String);
var
addProc : TADOStoredProc;
param : TParameter;
field : TField;
dataStream : TFileStream;
begin
if FileExists(sourcePath) then
begin
dataStream := TFileStream.Create(sourcePath, fmOpenREad or fmShareDenyNone);
try
addProc := TADOStoredProc.Create(nil);
addProc.Connection := dbCon;
addProc.ProcedureName := 'spAddToSolve';
param := addProc.Parameters.AddParameter;
param.Name := '#SolveData';
param.DataType := ftBlob;
//not sure what to do next
param.Value := dataStream; //Types are not compatable
addProc.Open;
finally
addProc.Free();
dataStream.Free();
end;
end;
end;
Your second try is on the right track. This should work:
param.DataType := ftBlob;
param.LoadFromStream(dataStream);
Related
Thanks to the below functions, I am succesfully retrieving, from a Word document stored locally (synced with the Server through OneDrive), its Server properties (those which are stored as SharePoint columns), all this without Ole automation. The functions' structure is:
Since the Word document is a zipped file, unzip the file where such properties are stored.
Extract the contents of the file into a string.
Load the string into an XML document.
Feed the field names and their contents into a StringList.
``
function WordGetServerProperties (FName:string):TStringList;
var
s,ss:string;
i,ii:integer;
St:TStringList;
XML:IXMLDocument;
N,NN: IXMLNode;
begin
s:=ExtractZipToStr(FName,'customXml/item1.xml',ExtractFilePath(FName));
if StrContains('<p:properties',s)=False then
s:=ExtractZipToStr(FName,'customXml/item2.xml',ExtractFilePath(FName));
if StrContains('<p:properties',s)=False then
s:=ExtractZipToStr(FName,'customXml/item3.xml',ExtractFilePath(FName));
XML:=NewXMLDocument;
St:=TStringList.Create;
XML.Active := True;
XML.LoadFromXML(s);
N:=xml.DocumentElement;
try
for i := 0 to N.ChildNodes.Count -1 do
begin
if N.ChildNodes[i].NodeName = 'documentManagement' then
begin
NN:=N.ChildNodes[i];
for ii := 0 to NN.ChildNodes.Count -1 do
begin
ss:=AnsiReplaceStr(NN.ChildNodes[ii].NodeName,'_x0020_',' ');
if ss='SharedWithUsers' then continue;
ss:=ss+'='+NN.ChildNodes[ii].Text;
st.Add(ss)
end;
end;
end;
finally
XML.Active := False;
end;
Result:=st;
end;
function ExtractZipToStr(const ZipFileName: string; const ZippedFileName, ExtractedFileName: string): widestring;
var
ZipFile: TZipFile;
F,s:string;
i:integer;
Exists:Boolean;
LStream: TStream;
FStream:TFileStream;
LocalHeader: TZipHeader;
begin
Exists:=False;
ZipFile := TZipFile.Create;
LStream := TStream.Create;
try
try
ZipFile.Open(ZipFileName,zmRead);
except on EZipException do begin Result:='noprops'; ZipFile.Close; ZipFile.Free; LStream.Free; exit; end; end;
for i := 0 to ZipFile.FileCount - 1 do
begin
F:= ZipFile.FileNames[i];
if F='docProps/custom.xml' then begin Exists:=True; system.Break; end;
end;
if exists=True then
begin
ZipFile.Read(ZippedFileName, LStream, LocalHeader);
LStream.Position:=0;
Result:=StreamToString(LStream);
end
else Result:='noprops';
finally
ZipFile.Close;
ZipFile.Free;
LStream.Free;
end;
end;
function StreamToString(aStream: TStream): widestring;
var
SS: TStringStream;
begin
if aStream <> nil then
begin
SS := TStringStream.Create('');
try
SS.CopyFrom(aStream, 0);
Result := SS.DataString;
finally
SS.Free;
end;
end else
begin
Result := '';
end;
end;
This is relatively fast but as not as much as I would like. Hopefully I have shown that (being amateur at this) I am at the end of my wits. Would you see any way to either improve or utterly replace these routines by something more efficient?
I'm using Delphi 5 Enterprise because that's what the program I'm working with was written in. I have written a procedure which saves bitmaps to an Access database quite happily. Now I want to be able to retrieve the bitmaps. Saving the bitmaps, I use SaveToStream. Retrieving them, I used LoadFromStream but the compiler tells me that it doesn't recognise that function. The code is below:
procedure TForm1.Button2Click(Sender: TObject);
var
Field : TBlobField;
Stream : TStream;
BMap : TBitMapImage;
begin
if BloBQuery.Active then
begin
Field := TBlobField(BlobQuery.FieldByName('Blob'));
Stream := BlobQuery.CreateBlobStream(Field, bmRead);
BMap := TBitMapImage.Create;
try
Image2.Picture.Graphic := BMap.LoadFromStream(Stream);
finally
BMap.Free;
Stream.Free;
end;
end;
end;
Can anyone tell me when LoadFromStream won't work? It seems odd! Thanks.
The code which wrote the bitmap was:
procedure TForm1.Button1Click(Sender: TObject);
var
Field : TBlobField;
Stream : TStream;
begin
if (BlobQuery.Active = True) and (Image1.Picture.Graphic <> nil) then begin
BlobQuery.Insert;
Field := TBlobField(BlobQuery.FieldByName('Blob'));
Stream := BlobQuery.CreateBlobStream(Field, bmWrite);
try
Image1.Picture.Graphic.SaveToStream(Stream);
finally
Stream.Free;
BlobQuery.Post;
end;
end;
end;
Assuming Image1.Picture.Graphic was pointing at a TBitmap object when you saved it to the DB, you need to use a TBitmap object instead of a TBitMapImage object when reading the image back out, eg:
procedure TForm1.Button2Click(Sender: TObject);
var
Field : TBlobField;
Stream : TStream;
BMap : TBitmap;
begin
if BlobQuery.Active then
begin
Field := TBlobField(BlobQuery.FieldByName('Blob'));
Stream := BlobQuery.CreateBlobStream(Field, bmRead);
try
BMap := TBitmap.Create;
try
BMap.LoadFromStream(Stream);
Image2.Picture.Graphic := BMap;
finally
BMap.Free;
end;
finally
Stream.Free;
end;
end;
end;
Alternatively:
procedure TForm1.Button2Click(Sender: TObject);
var
Field : TBlobField;
Stream : TStream;
begin
if BlobQuery.Active then
begin
Field := TBlobField(BlobQuery.FieldByName('Blob'));
Stream := BlobQuery.CreateBlobStream(Field, bmRead);
try
Image2.Picture.Bitmap.LoadFromStream(Stream);
finally
Stream.Free;
end;
end;
end;
I would like to send a bitmap image with an HTTP POST method. How can I send it to a URL?
I am using Indy 10 and Delphi 10.1. In a procedure, I create a TStringList with all parameter values, but I don't know how to pass the bitmap data.
This is my code:
procedure TuDm_Athlos.AddComandaInsertLogo(workList: TStringList;
imageStream: TStream);
var
image : TBitmap;
begin
try
image := TBitmap.Create;
imageStream := TStream.Create;
image.LoadFromFile('D:\\COFEE.BMP');
image.SaveToStream(imageStream);
workList.Add('db=titles');
workList.Add('line_1=');
worklist.Add('line_2=');
workList.Add('line_3=');
workList.Add('line_4=');
workList.Add('line_5=');
workList.Add('line_6=');
workList.Add('store=&DB=PRN_UDG');
workList.Add('code=1');
workList.Add('width=' + IntToStr(image.Width));
workList.Add('height=' + IntToStr(image.Height));
workList.Add('length=576');
workList.Add('store=');
finally
FreeAndNil(imageStream);
end;
end;
function TuDm_Athlos.InsertLogo(imageStream: TStream;
isFullResponse: Boolean): Boolean;
var
StrResult : UTF8String;
workList : TStringList;
ContentStream : TStream;
image : TBitmap;
begin
//Setup;
Result := False;
try
try
workList := TStringList.Create;
ContentStream := TStream.Create;
image := TBitmap.Create;
image.LoadFromStream(imageStream);
AddComandaInsertLogo(workList,imageStream);
AddComandaSummarize(workList, False);
StrResult := IdHTTP1.Post(printerURL + 'db_status.xml?',workList);
ContentStream := StringToStream(strResult);
Result := XmlReadCommanda(imageStream); //XmlReadComanda(ContentStream);
except
on e : Exception do begin
//DisconnectHttpClient;
//raise Exception.Create(TranslateHttpError(e.Message));
end;
end;
finally
FreeAndNil(workList);
FreeAndNil(image);
ContentStream.Free;
end;
end;
You can send a file or stream using TIdMultiPartFormDataStream instead of TStringList.
uses
..., IdMultipartFormData;
procedure postImage(Url, FileName: String; imageStream: TStream);
var
Form : TIdMultiPartFormDataStream;
LStream: TStream;
begin
if imageStream = nil then
LStream := TIdReadFileExclusiveStream.Create(FileName)
else
LStream := imageStream;
try
Form := TIdMultiPartFormDataStream.Create;
try
Form.AddFormField('db', 'titles');
Form.AddFormField('line_1', '');
Form.AddFormField('line_2', '');
Form.AddFormField('line_3', '');
Form.AddFormField('line_4', '');
Form.AddFormField('line_5', '');
Form.AddFormField('line_6', '');
Form.AddFormField('store', '');
Form.AddFormField('DB', 'PRN_UDG');
Form.AddFormField('code','1');
Form.AddFormField('width', IntToStr(image.Width));
Form.AddFormField('height',IntToStr(image.Height));
Form.AddFormField('length','576');
Form.AddFormField('store','');
//CREATE A FIELD AND SET THE STREAM
Form.AddFormField('bitmap', '', '', LStream, FileName);
IdHTTP1.Post(Url, Form);
finally
Form.Free;
end;
finally
if imageStream = nil then
LStream.Free;
end;
end;
procedure postImage(Url, FileName : String);
begin
postImage(Url, FileName, nil);
end;
i need some help with my procedure. I want to save some strings in a stringlist which is created in another procedure. How can i do this?
I wrote a comment at the right place to understand it better.
procedure GetIniNamesWithoutExt(IniPfade: TStringList);
var
i, suchPunkt: integer;
ini: TIniFile;
Modul, fullFileName, IniName: String;
begin
try
for i := 0 to IniPfade.Count-1 do
begin
fullFileName := IniPfade.Strings[i];
Modul := ExtractFileName(fullFileName); // Dateiname aktueller Ini + .Ini Endung
suchPunkt := Pos('.', Modul);
IniName := Copy(Modul, 1, suchPunkt-1); // Aktueller Modulname ohne ini Endung
// Here should be the Code for saving the String "IniName" to a StringList which is created in procedure a. Procedure a calls the procedure GetIniNamesWithoutExt.
end;
finally
end;
end;
How about
procedure GetIniNamesWithoutExt(IniPfade, Module: TStrings);
var
i, suchPunkt: integer;
ini: TIniFile;
Modul, fullFileName, IniName: String;
begin
Module.BeginUpdate;
try
for i := 0 to IniPfade.Count-1 do
begin
fullFileName := IniPfade.Strings[i];
Modul := ExtractFileName(fullFileName); // Dateiname aktueller Ini + .Ini Endung
suchPunkt := Pos('.', Modul);
IniName := Copy(Modul, 1, suchPunkt-1); // Aktueller Modulname ohne ini Endung
Module.Add(IniName);
end;
finally
Module.EndUpdate;
end;
end;
and from procedure A:
procedure A;
var
Module: TStringList;
begin
Module := TStringList.Create;
try
GetIniNamesWithoutExt(IniPfade , Module);
// Do Whatever you want with "Module"
finally
Module.Free;
end;
end;
I try to insert into blob field in SQLite with Delphi XE3.
I've been using TDBXCommand and TSQLConnection like this.
but blob field is not inserted and even i cannnot get any result from query
procedure TDBXCommandHelper.Init(const AQry: String);
begin
Parameters.ClearParameters;
Close;
Prepare;
Text := AQry;
end;
procedure dmDB.InsertPicture;
const
QRY = 'INSERT INTO Memo(Picture) VALUES(?)';
var
LTransaction: TDBXTransaction;
LBlob: TDBXParameter;
LStream: TFileStream;
begin
LTransaction := FDBCon.BeginTransaction;
LStream := TFileStream.Create('d:\sample.bmp', fmOpenRead);
LBlob := TDBXParameter.Create;
try
try
FDBXCmd := FDBCon.DBXConnection.CreateCommand;
FDBXCmd.CommandType := TDBXCommandTypes.DbxSQL;
FDBXCmd.Init(QRY);
LBlob.DataType := TDBXDataTypes.BlobType;
LBlob.SubType := TDBXSubDataTypes.BinarySubType;
LBlob.Value.SetStream(LStream, False);
FDBXCmd.Parameters.AddParameter(LBlob);
FDBXCmd.ExecuteUpdate;
except
on E: Exception do
FDBCon.RollbackFreeAndNil(LTransaction);
end;
FDBCon.CommitFreeAndNil(LTransaction);
finally
FreeAndNil(LStream);
FreeAndNil(LBlob);
end;
end;
using TSQLConnection but i cannot get any result
procedure TInsertThread.NoteInsertExcute;
const
QRY = 'INSERT INTO Memo(Picture) VALUES(:Picture)';
var
LTransaction: TDBXTransaction;
LParams: TParams;
LStream: TMemoryStream;
begin
LTransaction := FDBCon.BeginTransaction;
LParams := TParams.Create(nil);
LStream := TMemoryStream.Create;
LStream.LoadFromFile(FValues.Values[NAME_PICTURE]);
try
LParams.CreateParam(ftBlob, 'Picture', ptInput);
LParams.ParamByName('Picture').LoadFromStream(LStream, ftBlob);
FDBCon.Execute(QRY, LParams);
FDBCon.CommitFreeAndNil(LTransaction);
finally
FreeAndNil(LStream);
FreeAndNil(LParams);
end;
end;
That's easy like:
var
ms: TMemoryStream;
sq: TSQLQuery;
begin
ms := TMemoryStream.Create;
ms.LoadFromFile('C:\Pictures\l.jpg');
if ms <> nil then
begin
sq := TSQLQuery.Create(nil);
sq.SQLConnection := con1;
sq.SQL.Text := 'update db1 set picture= :photo ;';
sq.Params.ParseSQL(sq.SQL.Text, true);
sq.Params.ParamByName('photo').LoadFromStream(ms, ftBlob);
sq.ExecSQL();
end;
.
Where con1 is a TSQLConnection.
You can try the following:
function GetFileAsBytesValue(AFileName: TFileName): TArray<Byte>;
var
Len: Integer;
LStream: TMemoryStream;
begin
LStream := TMemoryStream.Create;
try
LStream.LoadFromFile(AFileName);
Len := LStream.Size;
SetLength(Result, Len);
Move(LStream.Memory^, Result[0], Len);
finally
LStream.Free;
end;
end;
procedure dmDB.InsertPicture;
const
QRY = 'INSERT INTO Memo(Picture) VALUES(?)';
var
LTransaction: TDBXTransaction;
LDBXCmd: TSQLQuery;
LParam: TParam;
begin
LTransaction := FDBCon.BeginTransaction;
LDBXCmd := TSQLQuery.Create(FDBCon);
try
try
LDBXCmd.SQLConnection := FDBCon;
LDBXCmd.SQL.Text := QRY;
LParam := LDBXCmd.Params.CreateParam(ftBlob, 'Picture', ptInput);
LParam.AsBlob := GetFileAsBytesValue('d:\sample.bmp');
LDBXCmd.ExecSQL;
except
on E: Exception do
FDBCon.RollbackFreeAndNil(LTransaction);
end;
FDBCon.CommitFreeAndNil(LTransaction);
finally
LDBXCmd.Free;
end;
end;