2015-11-28 40 views
0

Мне нужно прочитать изображение JPG, хранящееся в XML-файле, и вставить его в поле blob в базе данных SQLite.SQLite - Как вставить изображение в формате JPG из файла XML (используя Delphi 2009)

Я могу сделать части этого уже, как показано ниже в коде, но нам нужна помощь по его объединению. Может кто-нибудь, пожалуйста, покажите мне, как прочитать текстовый файл bitmap в файле XML и вставить его в поле blob в базе данных?

Это то, что я уже могу сделать.

Я могу прочитать файл XML с помощью Дельх данных XML блока и хранения текстового материала Binding из него в базе данных, используя следующий (упрощенный) код:

procedure TForm1.BtnReadXML(Sender: TObject); 
var 
    sql : string; 
    Data : XML_Binding_Photos.IXMLSuperStarReportType; 
    RecNum : integer; 

begin 
Data := XML_Binding_Photos.LoadSuperStarReport ('Photos.xml'); 
Database1.Open; 
try 
    RecNum := 2; 
    SQL := 'INSERT INTO main.Photos (id , firstname) VALUES (Data.record_[RecNum].ID, Data.record_[RecNum].Fname) ;' ; 
    Query1.Close; 
    Query1.selectSQL := sql; //insert the data 
    Query1.Open ; 
finally 
    Database1.Close; 
end; 
end; 

Я также могу вставить JPG изображение с диска в базу данных, используя потоки, как это:

procedure TForm1.Insert_JPG_PhotoFromFile(Sender: TObject); 
var 
    strm : TmemoryStream ; 
begin 
Database1.Open; 
strm := TmemoryStream.Create; 
try 
    strm.LoadFromFile('C:\...\testpic2.jpg'); 
    Query1.Close; 
    Query1.selectSQL := ('INSERT INTO main.Photos (id, photo) VALUES (''999'', :photo)'); 
    Query1.Params.ParamByName('photo').LoadFromStream(Strm,ftGraphic); 
    Query1.Open ; 
finally 
    strm.Free ; 
    DISQLite3Database1.close; 
end; 
end; 

Но мой файл XML имеет JPG изображение в нем, кодируется следующим образом:

<Record> 
    <ID>14046</ID> 
    <Fname>Fred</Fname> 
    <Photo>/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAE - lots more of the same - txNxvd8dc44Htz/Ktx3Oe3T/AB96KK6DA//Z </Photo> 
    </Record> 

Я могу прочитать символы, составляющие растровое изображение, в строку или StringStream, используя блок привязки данных XML, но, похоже, не может корректно его сохранить в виде блоба в базе данных.

(Я не хочу сначала сохранять каждый образ XML на диск как jpg, частично как его уже на диске в другой форме, а частично - тысячи этих изображений в XML-файле. Также для других причины, я хочу поместить изображение в базу данных, а не поместить его на диск и просто сохранить имя файла)

+0

Вы знаете, как получить поток из файл и как сохранить поток в db. Таким образом, ваш реальный вопрос может быть сведен к: Как получить данные изображения из xml в поток. Может быть, этот реальный вопрос приведет вас к ответу: o) –

+0

После большего количества исследований данные, вероятно, будут закодированы в base64 и, возможно, jpg не bmp. Я использовал компонент Indy TIdDecoderMIME, то есть PhotoData: = IdDecoderMIME1.DecodeString (PhotoData); а затем посмотрел на результат в шестнадцатеричном формате, и он начинается с FFD8, который, как я понимаю, означает, что это jpg. Поэтому я попытался создать поток, используя TheStream.Write (PhotoData [1], Length (PhotoData)); а затем Query1.Params.ParamByName ('the_photo'). LoadFromStream (TheStream, ftGraphic); но я все еще не получаю нужного изображения в базе данных (там есть изображение, но его только цветные квадраты и странные символы – user3209752

+0

Строка Base64 - это закодированный поток. Просто найдите строку base64 для потокового декодера; o) –

ответ

0

Это работает, чтобы сделать изображение из файла XLM и вставить его в базу данных sqlite в поле blob ,

В этом коде используется блок привязки XML-данных, чтобы было проще читать кодированное изображение base64 из XML-файла в виде строки, хранящейся в Base64PhotoData. Затем он использует компонент Indy TIdDecoderMIME, который я вставлял в форму (IdDecoderMIME1: TIdDecoderMIME), чтобы декодировать base64 на переменную типа Tbytes (называемую DecodeBytes) Затем для хранения этого массива байтов в поле blob каждый байт должен быть преобразован обратно в шестнадцатеричный, и все, что добавлено «х», чтобы указать, что оно находится в шестнадцатеричном виде.
Это решение не нуждается в потоки (хотя, возможно, он может быть преобразован, чтобы сделать так, если этот подход лучше)

(Все цитаты являются одинарные кавычки)

Procedure TForm1.btnimportphotosfromxmlClick(Sender: TObject); 
var 
    sql : string; 
    XMLData : XML_Binding_Photos.IXMLStarReportType; //in unit XML_Binding_Photos 
    i : integer; 
    Base64PhotoData, DecodedPhotoData : ansistring; 
    DecodeBytes: TBytes; 
    PhotoBlobs : string; 
begin 
XMLData := XML_Binding_Photos.LoadStarReport ('Photos.xml');  //open xml as a IXMLStarReportType , created from the xml file with the XML data binding wizard 
Base64PhotoData := SIMSData.record_[2].Photo;       //get the xml photo data from xml file, in this test case the second record 
DecodeBytes := IdDecoderMIME1.DecodeBytes(Base64PhotoData) ; //decode base64 charater string to an array of bytes 

PhotoBlobs := '';           //initialsise the string we are going to insert into the blob field 
for i := 0 to high(DecodeBytes) do    //convert each byte to a hex charater so that it can be inserted into a blob 
      PhotoBlobs := PhotoBlobs + inttohex(DecodeBytes[i],2); 

SQL := '' 
+'INSERT ' 
+'INTO StudentPhotos (id, photo ) ' 
+'  VALUES (''777'', ' 
+'    x''' + PhotoBlobs +''') ' ;       // note the prepending of lower case x to the hex byte string 


DISQLite3Database1.DatabaseName := 'C:\...\testphoto.db'; 
DISQLite3Database1.open 
try 
    DISQLite3Database1.Execute(sql); 
finally 
    DISQLite3Database1.close; 
end; 
+0

Существует класс, называемый 'TBytesStream', и вы получите поток из' TBytes', см. Http://docwiki.embarcadero.com/Libraries/en/System.Classes.TBytesStream.Create –

+0

Спасибо, я посмотрю что, хотя я не уверен, какая разница, используя пары, сделает этот ответ. – user3209752