Konuyu Oyla:
  • Derecelendirme: 5/5 - 1 oy
  • 1
  • 2
  • 3
  • 4
  • 5
Database'e Resim Yükleme (Base64toİmage)
#1
Photo 
Merhaba,
Daha önce paylaşıldımı mı bilmiyorum ama bana lazım olan birşeyi sizinle de paylaşmak istedim.

Uygulamalarımızda resim göstermek isteriz. Göstermek istediğimiz resim genelde bir yere upload edip oradan idhttp ile çekip göstermek gibi bir yöntem gelir aklımıza ama daha hızlı ve daha kullanışlı bir yöntem daha mevcut. Bu yöntem kısaca önce bir resmi base64'e çevirip bu base64 çıktısını mysql'e kaydedip resmi göstermek istediğimiz yerde mysql'den çekip base64 to image yaparak resmi göstermektir.

Böylelikle herhangi bir yere upload etmeden kolayca resminizi gösterebiliyorsunnuz.

r5Rzpa.jpg


Kodlama biraz özensizce olabilir kusura bakmayın

kodlar şu şekilde;

unit Unit1;

interface

uses
 System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
 FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Objects,
 FMX.StdCtrls, FMX.Controls.Presentation, FMX.Edit, IdBaseComponent, IdCoder,
 IdCoder3to4, IdCoderMIME, FMX.ScrollBox, FMX.Memo;

type
 TForm1 = class(TForm)
   Button1: TButton;
   Image1: TImage;
   IdDecoderMIME1: TIdDecoderMIME;
   Memo1: TMemo;
   OpenDialog1: TOpenDialog;
   Edit1: TEdit;
   Button2: TButton;
   IdEncoderMIME1: TIdEncoderMIME;
   Button3: TButton;
   procedure Button1Click(Sender: TObject);
   procedure Button2Click(Sender: TObject);
   procedure Button3Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

{$R *.fmx}

procedure TForm1.Button1Click(Sender: TObject);
var
 S: String;
 Strm: TMemoryStream;
begin
Strm := TMemoryStream.Create;
 try
 S:=memo1.Text;
   TIdDecoderMIME.DecodeStream(S, Strm);
   Strm.Position := 0;
   Image1.Bitmap.LoadFromStream(Strm);
 finally
   Strm.Free;
 end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
S: String;
Strm:TFilestream;
begin

Strm:=TFilestream.Create(edit1.Text,fmOpenRead);
s:=IdEncoderMIME1.EncodeStream(Strm) ;
Memo1.Text:=S;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
if OpenDialog1.Execute then
begin
edit1.Text:=OpenDialog1.FileName;
end;
end;

end.

Örnek uygulamayı da ekte paylaştım kolay gelsin
Cevapla
#2
Hexlesek de base64 lesek de dosya boyutu büyümüyor aynı kalıyor. Hexlesek tekrar hextoimage yapamıyoruz ama base64 için bu mümkün diye biliyorum. Ayrıca bence base64toimage yöntemi bir resmi siteye upload edip idhttp ile çekmekten daha kullanışlı o uygulamaya ait resimler bir karışıklık olmadan tek bir yerde toplanıyor kaybolma silinme gibi sorunlar yaşamıyosunuz sizin kontrolünüzde herşey
Cevapla
#3
Merhaba,

(23-12-2018, Saat: 03:49)okoca Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.base64 lediğinde jpg binary datası ne kadar büyüyor? hex lesek en fazla 2 katına çıkar, veya binary olarakda yollayabilirsin, base64 ile text olarak yazıyorsun, veritabanında resim depolamak etik değildir.

"Veri tabanında resim depolamak etik değildir" çok ezber bir cümle olmuş. Veri tabanında dosya tutmak bir kaç sebepten dolayı sevilmez:

1. İlişkisel veri tabanları genel olarak dosyalar için değil, basit veri tipleri için tasarlanır. Genelde de B-Tree veya bunun biraz daha geliştirilmiş yöntemleri kullanılır. İşte büyük veriler burada problem yaratır. Ve veri tabanının performansını çok düşürür. Bu kural aslında sadece dosyalar için değil, TEXT, NTEXT veya VARCHAR(MAX) gibi çok büyük alanlar için de geçerlidir. Bunun detayları için veri tabanı sisteminin detaylarını okumak gerekir. 
2. Veri tabanını her yedeklediğinizde bu dosyaları da yedeklemiş olursunuz. İyi gibi görünebilir, ama bazı yan etkileri var. Örneğin yedekleme hızını inanılmaz derece düşüyor. Ayrıca yedekleme sisteminizde de çok ciddi bir yer israfı oluyor.
3. Dosyalara erişimin çok hızlı olmasına gerek yok, ama aynı durum diğer kayıtlar için geçerli değil. Eğer dosyaları veri tabanı içine ekleyecek olursanız, veri tabanı çok hızlı büyüyecek (sizin eklediğiniz 1 MB'lik bir dosyanın veri tabanındaki karşılığı çok daha fazla olabilir) ve bir süre sonra veri tabanını hızlı bir diske değil, büyük ama yavaş bir diske almanız gerekecek.
4. Sunucunun bellek ihtiyacı artabilir. Sonuçta veri tabanı sistemi bu bilgileri belleğe alacak ve size gönderecek. 

Aslında bu maddelerin hepsi şöyle özetlenebilir: Dosyaları veri tabanında tutacak olursanız ölçekleme sorunu yaşayabilirsiniz. Yani veri miktarı ve kullanıcı sayısı arttıkça sistemin performansı düşebilir.

Tam da burada yeni teknolojiler devreye giriyor. Diğer veri tabanlarını bilmiyorum, ama SQL Server bir sürümden sonra (hangi sürüm hatırlamıyorum) FileStream diye yenilik getirdi. Artık veri tabanına eklemek istediğiniz dosyalar diğer verilerle aynı veri tabanı dosyasına kaydedilmiyor. Bu sayede de yukarıda yazdığım sorunlar çözülmüş oluyor. FileStream olarak kullanmak istediğiniz dosyanın klasörünü de seçebiliyorsunuz. Yani dosyaları yavaş ama kapasitesi çok yüksek bir diske kaydedebiliyorsunuz. Dosyalara erişim için de özel bir şey yapmanıza gerek yok, normal veri erişim bileşenleri ile (Firedac, Unidac, ADO, Zeos vs) erişebiliyorsunuz. Ve belki de en güzeli: FileStream işlemleri transaction içine alınabiliyor. 

Ben hiç kullanmadım ve bu yazdıklarım da teorik bilgiler. Dikkat ederseniz kesin cümleler de kurmadım. Bu mesajı yazma sebebim de size bunu kullanmanızı tavsiye etmek değil. Sadece doğru sebeplerden dolayı karar vermenizi söylemek Smile . İhtiyacınıza göre FileStream kullanmadan, ama dosyaları da veri tabanı içine ekleyerek çözüm üretmek uygun olabilir. Olmaya da bilir Smile 

Bir de şundan bahsedeyim. Resim dosyalarını veri tabanında tutmak için bunları base64 ile encode/decode etmeye gerek yok. Base64 encode/decode başka bir amaç için geliştirilmiştir. Binary bir verinin, string bir şekilde tutulması/gösterilmesi/iletilmesi gerektiğinde kullanılır. Veri tabanını siz tasarladığınıza göre resimleri niye text field içinde tutasınız ki? Binary field tanımlayın, Delphi tarafında da o field zaten BlobField olarak görünecektir. DBImage gibi nesneler BlobField'den direkt resmi gösterebilir. Verileri de BlobField.SaveToFile/SaveToStream/LoadFromFile/LoadFromStream gibi fonksiyonlarla da dilediğiğiniz yönetebilirsiniz. 

Son olarak hex'e çevirmek diye bir şey de yok. Hexadecimal dediğiniz, sayıları daha kolay okumak için kullanılan bir yöntem. Programcılıkta sayıları 2 veya 10 tabanına göre değil, 16 tabanına göre okumak/yazmak daha kolaydır (Detaylarını okumak isteyene ingilizce ilk bulduğum linklerden birisi: Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.)

İyi çalışmalar
Cevapla
#4
(23-12-2018, Saat: 03:49)okoca Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.Veritabanında resim depolamak etik değildir.

Eskiden olsa haklıydınız. Ama artık bir çok veri tabanı programında bu dezavajların çözümü var. Ben her türlü bilginin veri tabanı üzerinde tutulması taraftarı biriyim. Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız. tartışmada ayrıntılı bilgi vermeye tartıştım.


(23-12-2018, Saat: 10:44)hakanharbeli Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.Hexlesek de base64 lesek de dosya boyutu büyümüyor aynı kalıyor.

Bir binary veriyi hex lemek veya base64 lemek veriyi uzatır. Boyut aynı kalıyor derken hangi iki veriyi karşılaştırıyorsunuz? Ayrıca özel bir amacınız yoksa veriyi (resmi, image ı) base64'te çevirene kadar zaten doğrudan MySql'deki BLOB veri türüne yükleme yapabilirsiniz.
WWW
Cevapla
#5
(23-12-2018, Saat: 12:32)csunguray Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.
(23-12-2018, Saat: 03:49)okoca Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.Veritabanında resim depolamak etik değildir.

Eskiden olsa haklıydınız. Ama artık bir çok veri tabanı programında bu dezavajların çözümü var. Ben her türlü bilginin veri tabanı üzerinde tutulması taraftarı biriyim. Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız. tartışmada ayrıntılı bilgi vermeye tartıştım.


(23-12-2018, Saat: 10:44)hakanharbeli Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.Hexlesek de base64 lesek de dosya boyutu büyümüyor aynı kalıyor.

Bir binary veriyi hex lemek veya base64 lemek veriyi uzatır. Boyut aynı kalıyor derken hangi iki veriyi karşılaştırıyorsunuz? Ayrıca özel bir amacınız yoksa veriyi (resmi, image ı) base64'te çevirene kadar zaten doğrudan MySql'deki BLOB veri türüne yükleme yapabilirsiniz.

evet bu konuyu biraz araştırdım boyutunu arttırıyor fakat çok sorun değil 7.5 kb lik resim 11 kb oluyor. Evet Blobfield' da kullanılabilir ama yine de base64'ü daha kullanışlı buldum yani base64 çıktısını her yerde kullanabiliyorum ama blobfield sadece mysql ya da database sınırlı bir uygulama gibi göründü gözüme
Cevapla
#6
Merhaba,
Ben Base64 olarak gelen veriyi image e çevirmek istiyorum. Delphi 6 kullanıyorum.
resim değişkenine veri geliyor ama çeviremiyor. Yardımlarınızı rica ediyorum.
Kod:

procedure TForm1.Button2Click(Sender: TObject);
var
 kargoHelper:IArasHelper;
 cevap:IArasResponseBarkod;
 resim:string;
 str:TStream;
begin
kargoHelper:=CoArasHelper.create;
 cevap:=kargoHelper.Barkod(
    'xxxxxxxxxxxxx',
    'xxxxx',
    'xxxx'
 );
 if cevap.ResultCode=0 then
 begin
   resim:=Decode64(cevap.Images);
   str:=TStringStream.Create(resim);
   Image1.LoadFromStream(str);
 end;
end;


function TForm1.Decode64(S: string): string;
var
  i: Integer;
  a: Integer;
  x: Integer;
  b: Integer;
begin
  Result := '';
  a := 0;
  b := 0;
  for i := 1 to Length(s) do
  begin
    x := Pos(s[i], codes64) - 1;
    if x >= 0 then
    begin
      b := b * 64 + x;
      a := a + 6;
      if a >= 8 then
      begin
        a := a - 8;
        x := b shr a;
        b := b mod (1 shl a);
        x := x mod 256;
        Result := Result + chr(x);
      end;
    end
    else
      Exit;
  end;
end;
Cevapla
#7
Merhaba,
Elde edilen base64 veriyi Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız. test edin. Veri bütünlüğünde bir sorun yoksa, resim elde etme kodunuzda bir sorun var demektir.
Delphi XE7 ve daha üst sürümleri için daha System.NetEncoding kütüphanesi içerisindeki TNetEncoding.Base64.Decode metodu kullanmanız daha iyi olacaktır.
While true do; Hayat döngüsü, kısır değildir! Yapılan bir yanlış, o döngünün dışına çıkmanızı sağlayacaktır.
WWW
Cevapla
#8
Şöyle eski ( unicode öncesi ) uyumlu bir örnek de ben yazayım.

function TForm1.EncodeBase64( aBitmap: TBitmap ): string;
 function Encode_Byte(b: Byte): char;
 const
   Base64Code: string[64] =
     'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
 begin
   Result := Base64Code[(b and $3F)+1];
 end;
var
 i         : Integer;
 SS        : TStringStream;
 strGelen  : String;
begin
 SS := TStringStream.Create( '' );
 try
   SS.Position := 0;
   aBitmap.SaveToStream( SS );
   strGelen := SS.DataString;
 finally
   SS.free;
 end;
 i       := 1;
 Result  := '';
 while i <= Length(strGelen) do
 begin
   Result := Result + Encode_Byte( Byte(strGelen[i]) shr 2);
   Result := Result + Encode_Byte((Byte(strGelen[i]) shl 4) or (Byte(strGelen[i+1]) shr 4));
   if i+1 <= Length(strGelen)
     then Result := Result + Encode_Byte((Byte(strGelen[i+1]) shl 2) or (Byte(strGelen[i+2]) shr 6))
     else Result := Result + '=';

   if i+2 <= Length(strGelen)
     then Result := Result + Encode_Byte(Byte(strGelen[i+2]))
     else Result := Result + '=';

   inc(i, 3);
 end;
end;

procedure TForm1.DecodeBase64(const strGelen: string; aBitmap:TBitmap);
const
  RESULT_ERROR = -2;
var
  idx       : Integer;
  uz        : Integer;
  c         : Char;
  i         : SmallInt;
  w         : Word;
  c4        : array[0..3] of SmallInt;
  strSonuc  : String;
  SS        : TStringStream;
begin
  strSonuc  := '';
  idx       := 1;
  w         := 0;
  uz        := Length(strGelen);

  while idx <= uz do
  begin
    while (idx <= uz) and (w < 4) do
    begin
      c := strGelen[idx];
      case c of
        '+'     : i := 62;
        '/'     : i := 63;
        '0'..'9': i := Ord© - (Ord('0')-52);
        '='     : i := -1;
        'A'..'Z': i := Ord© -  Ord('A');
        'a'..'z': i := Ord© - (Ord('a')-26);
      else
        i := RESULT_ERROR;
      end;

      if i <> RESULT_ERROR then
      begin
        c4[w] := i;
        inc(w);
      end;
      inc(idx);
    end;

    if w = 4 then
    begin
      w := 0;
      strSonuc := strSonuc + Char((c4[0] shl 2) or (c4[1] shr 4));
      if c4[2] = -1 then Exit;
      strSonuc := strSonuc + Char((c4[1] shl 4) or (c4[2] shr 2));
      if c4[3] = -1 then Exit;
      strSonuc := strSonuc + Char((c4[2] shl 6) or (c4[3]));
    end;
  end;
  SS := TStringStream.Create( strSonuc );
  try
    SS.Position := 0;
    aBitmap.LoadFromStream( SS );
  finally
    SS.free;
  end;
end;

Kullanımı
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
  Memo1.Lines.Text := EncodeBase64( Image1.Picture.Bitmap );
end;

procedure TForm1.BitBtn2Click(Sender: TObject);
begin
  DecodeBase64( Memo1.Lines.Text, Image2.Picture.Bitmap );
end;

ptnv5oazhujnpgp4dvlq.gif
Saygılarımla
Muharrem ARMAN

guplouajuixjzfm15eqb.gif


Cevapla


Konu ile Alakalı Benzer Konular
Konular Yazar Yorumlar Okunma Son Yorum
  Resim Yükleme SimaWB 14 2.384 11-12-2018, Saat: 16:05
Son Yorum: Bay_Y
  AnonymousThread ile ListView'e Veri Yükleme witalihakko 3 1.497 15-03-2017, Saat: 11:54
Son Yorum: Tuğrul HELVACI



Konuyu Okuyanlar: 1 Ziyaretçi