Итак, в данном посте усовершенствуем алгоритм с отправкой файла(изображения) с клиента на сервер через строку. Это сделано для того, чтобы избежать потенциального обрезания строки терминирующим нулем.
Алгоритм хорошо работает для файлов до 3 мб. Файл в 6 мб. уже подвешивает систему, поэтому нужно сделать передачу по частям, это я проделаю в следующем посте.
Также, для обратной задачи – передать файл с сервера на клиент – нужно проявить немного фантазии и проделать все тоже самое, только наоборот.
Алгоритм будет таким…
-На клиенте запаковать строку в вариантный массив
-Отправить вариантный массив в качестве OleVariant на сервер
-На сервере распаковать вариантный массив в строку
-Превратить строку в файл (изображение)
-Загрузить в СУБД
Что делаем на сервере?
Пишем функцию распаковки из OleVariant в String…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
function OleVariantToString(const Value: OleVariant): string; var ss: TStringStream; Size: integer; Data: PByteArray; begin Result:=''; if Length(Value) = 0 then Exit; ss:=TStringStream.Create; try Size := VarArrayHighBound (Value, 1) - VarArrayLowBound(Value, 1) + 1; Data := VarArrayLock(Value); try ss.Position := 0; ss.WriteBuffer(Data^, Size); ss.Position := 0; Result:=ss.DataString; finally VarArrayUnlock(Value); end; finally ss.Free; end; end; |
Распаковка + запись в СУБД
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
procedure TServerMethods1.DataInsert(V: Olevariant); var s:string; ss:tstringstream; begin s:=OleVariantToString(V); ss:=tstringstream.Create(s); ss.Position:=0; simpledataset1.insert; simpledataset1.fieldbyname('Primary_key').AsInteger:=simpledataset1.RecordCount+1; tblobfield( simpledataset1.fieldbyname('Picture')).LoadFromStream(ss); simpledataset1.post; simpledataset1.applyUpdates(-1); end; |
Что делаем на клиенте?
Пишем функцию “Из строки в OleVariant”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
function StringToOleVariant(const Value: string): OleVariant; var Data: PByteArray; ss: TStringStream; begin Result:=null; if Value='' then Exit; ss:=TStringStream.Create(Value); try Result := VarArrayCreate ([0, ss.Size - 1], varByte); Data := VarArrayLock(Result); try ss.Position := 0; ss.ReadBuffer(Data^, ss.Size); finally VarArrayUnlock(Result); end; finally ss.Free; end; end; |
Далее на кнопку “вешаем” следующий обработчик
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
procedure TForm3.Button4Click(Sender: TObject); var smc:tservermethods1client; i:integer; bmp:tbitmap; twic:twicimage; ss:tstringstream; s:string; begin bmp:=tbitmap.Create; twic:=twicimage.Create; ss:=tstringstream.Create; //Загрузка картинки в память... opendialog1.Execute; twic.LoadFromFile(opendialog1.FileName); bmp.Assign(twic); bmp.SaveToStream(ss); smc:=tservermethods1client.Create(sqlconnection1.DBXConnection); s:=ss.DataString; smc.DataInsert(StringToOleVariant(s)); smc.Free; clientdataset1.Refresh; bmp.Free; twic.Free; ss.Free; s:=''; end; |