Delphi Can

Orjinalini görmek için tıklayınız: Cloudinary Image Upload Tool ( Forum image boyutlandırma opsiyonlu )
Şu anda (Arşiv) modunu görüntülemektesiniz. Orjinal Sürümü Görüntüle internal link
Sayfalar: 1 2
Foruma eklenecek resimler konusunda kendi kullanımım için hazırladığım yardımcı bir toolu paylaşayım dedim. 
  • "REST ile nasıl dosya gönderilir" 
  • "Cloudinary.com'dan açılan hesapta dosya göndermek için API Preset ve API Cloud Name nasıl alınır?" 
    ...konularını @SimaWB 'nin açtığı konuda bulabilirsiniz. bkz. DelphiCan linki

Bu paylaştığım tool bünyesinde : 
  • Gönderilen dosyaların kaydını tutmak
  • Gönderilen dosyaların dilediğiniz zaman copy/paste ile Uri, Path bilgilerini tek tıklamayla almak.
  • DelphiCan forumda küçültülmüş önizleme ile üzerine tıklayınca tam boyutunun yeni pencerede görüntülenebildiği boyutlandırma özelliği mevcuttur.
Tool'un form boyutunu değiştirerek yanı başındaki resmin de canlı olarak ölçekli olarak yeniden boyutlandığını görebilirsiniz.
Delphican forumda görmek istediğiniz boyutlandırma bu şekilde sizin tarafınızdan otomatik yapılmaktatır.

Küçültülmüş boyuttan memnunsanız "Image Link Generator" butonu ile de ilgili resim linkinin yeniden ölçeklendirilmiş halinin linki oluşturulmaktadır. 

Üretilen bu linki direkt DelphiCan "Gelişmiş Mesaj Arayüzü" modunda metin olarak yapıştırmanız kafidir. Mesaj penceresindeki "resim ekle" butonuna basmaya gerek yoktur. Kopyala / yapıştır yapılır yapılmaz resim, ayarladığınız boyutta karşınıza gelir.
     
örneğin bu şekil


mqjhyrhumqx5xstsu9wf.png


Kullanımı :
  • ZIP paketini bir klasöre açınız. (portable tek dosya)
  • İlk çalıştırdığınızda göreceğiniz iki adet check box'a ayrı ayrı basarak Cloudinary.com sitesindeki anonim hesabınızın 
         API "Preset"      API "Cloud Name"  
  • bilgileri istenecektir. Bunları aynı klasörde oluşturulan INI dosyasına kaydedecek bir daha sormayacaktır. 
  • Artık dosya yüklemeye hazır. 
Bilgi güvenliği gereği özel fotoğraflarınızın olduğu değil, sadece forumda paylaşacağınız resimler için önem derecesi düşük profilli bir hesap açmanız kafidir.  Idea  


q5qsozwoie41cduzcqiq.gif

image_0_base.php?case=Image_Upload.zip



Projenin bir CloudinaryUploader ismindeki unit altında hazırladığım sınıf tarafını da sizin için buradan paylaşayım. 
Projenin ana motoru bu aşağıdakidir, main form sadece kullanıcı arayüzüdür.

Benzerini kendisi üretmek isteyenler olabilir, kolaylık sağlaması dileklerimle.

unit CloudinaryUploader;

interface

Uses  System.Classes, System.SysUtils, System.JSON, System.UITypes, StdCtrls,
     REST.Client, REST.Types,
     Vcl.Clipbrd,  Vcl.Dialogs, Vcl.ExtDlgs,
     Vcl.Graphics, Vcl.Imaging.JPEG, Vcl.Imaging.PNGImage, Vcl.Imaging.GIFImg;

type
 TSentResult = Record
   success, failed : Integer;
 end;
type
 PImageRec = ^TImageRec;
 TImageRec = Record
   FileName      : String;
   Width, Height : Integer;
   Uri           : String;
 end;
 PImageArray = Array of PImageRec;

type
 TCloudinaryHelper = class (TObject)
 private
   Const
     FAPI_resource_Type  = 'image';
   var
     FSelectedImageList  : PImageArray;
     FGlobalImageList    : PImageArray;
     FAPI_UnsignedUpload_Preset  : String;
     FAPI_cloud_Name             : String;

   procedure   ClearList( var aList: PImageArray );
   procedure   AddSentImagesToGlobal;
   function    GetSelectedImage( index: Integer ): TImageRec;
   function    GetSelectedImageCount : Integer;
   function    GetGlobalImage(index: Integer): TImageRec;
   function    GetGlobalImageCount : Integer;
 public
   constructor Create;
   destructor  Destroy; override;
   property    API_UnsignedUpload_Preset : string read FAPI_UnsignedUpload_Preset write FAPI_UnsignedUpload_Preset;
   property    API_cloud_Name            : string read FAPI_cloud_Name write FAPI_cloud_Name;
   property    SelectedImages[index: integer] : TImageRec read GetSelectedImage;
   property    SelectedImageCount        : integer   read GetSelectedImageCount;
   property    AllImageCount             : integer   read GetGlobalImageCount;
   property    AllImages[index: integer] : TImageRec read GetGlobalImage;
   procedure   SaveListAllImages( aFileName: String );
   procedure   SaveListSelectedImages( aFileName: String );
   procedure   LoadListAllImages( aFileName: String );
   procedure   LoadListSelectedImages( aFileName: String );
   function    DoSelectImages: boolean;
   function    DoSendImages : TSentResult;
   procedure   MsgDlg( aMsg: String );
 end;

var
 xCloudinary : TCloudinaryHelper;

implementation

{ TCloudinaryHelper }

constructor TCloudinaryHelper.Create;
begin
 inherited;

end;

destructor TCloudinaryHelper.Destroy;
begin
 ClearList(FSelectedImageList);
 ClearList(FGlobalImageList);
 inherited;
end;


function TCloudinaryHelper.GetSelectedImage(index: Integer): TImageRec;
begin
 Result.FileName := FSelectedImageList[index].FileName;
 Result.Width    := FSelectedImageList[index].Width;
 Result.Height   := FSelectedImageList[index].Height;
 Result.Uri      := FSelectedImageList[index].Uri;
end;

function TCloudinaryHelper.GetSelectedImageCount: Integer;
begin
 Result := High(FSelectedImageList)+1;
end;

function TCloudinaryHelper.GetGlobalImage(index: Integer): TImageRec;
begin
 Result.FileName := FGlobalImageList[index].FileName;
 Result.Width    := FGlobalImageList[index].Width;
 Result.Height   := FGlobalImageList[index].Height;
 Result.Uri      := FGlobalImageList[index].Uri;
end;

function TCloudinaryHelper.GetGlobalImageCount: Integer;
begin
 Result := High(FGlobalImageList)+1;
end;

procedure TCloudinaryHelper.AddSentImagesToGlobal;
var
 i: Integer;
begin
 if high(FSelectedImageList) < 0 then Exit;

 for i := Low(FSelectedImageList) to High(FSelectedImageList) do begin
   if FSelectedImageList[i].Uri <> '' then begin
     if High(FGlobalImageList) < 0 then SetLength(FGlobalImageList ,1) else SetLength(FGlobalImageList ,High(FGlobalImageList)+2);
     new( FGlobalImageList[ High(FGlobalImageList) ] );
     FGlobalImageList[High(FGlobalImageList)].FileName := FSelectedImageList[i].FileName;
     FGlobalImageList[High(FGlobalImageList)].Width    := FSelectedImageList[i].Width;
     FGlobalImageList[High(FGlobalImageList)].Height   := FSelectedImageList[i].Height;
     FGlobalImageList[High(FGlobalImageList)].Uri      := FSelectedImageList[i].Uri;
   end;
 end;
end;

procedure TCloudinaryHelper.ClearList( var aList: PImageArray );
var
 i: Integer;
begin
 if high(aList) < 0  then exit;
 for i := Low(aList) to High(aList) do
   Dispose(  aList[i] );
 Finalize( aList );
end;

procedure TCloudinaryHelper.SaveListAllImages(aFileName: String);
var
 i : Integer;
begin
 if High(FGlobalImageList) < 0 then exit;

 With TStringList.Create do try
   for i := Low(FGlobalImageList) to High(FGlobalImageList) do begin
     add( Format( '%s|%s|%s|%s|%s', [
           ExtractFileName( FGlobalImageList[i].FileName )
         , FGlobalImageList[i].Width.ToString
         , FGlobalImageList[i].Height.ToString
         , ExtractFilePath( FGlobalImageList[i].FileName )
         , FGlobalImageList[i].Uri
      ] ) );
   end;
   SaveToFile( aFileName );
 finally
   free;
 end;
end;

procedure TCloudinaryHelper.SaveListSelectedImages(aFileName: String);
var
 i : Integer;
begin
 if High(FSelectedImageList) < 0 then exit;

 With TStringList.Create do try
   for i := Low(FSelectedImageList) to High(FSelectedImageList) do begin
     add( Format( '%s|%s|%s|%s|%s', [
           ExtractFileName( FSelectedImageList[i].FileName )
         , FSelectedImageList[i].Width.ToString
         , FSelectedImageList[i].Height.ToString
         , ExtractFilePath( FSelectedImageList[i].FileName )
         , FSelectedImageList[i].Uri
      ] ) );
   end;
   SaveToFile( aFileName );
 finally
   free;
 end;
end;

procedure TCloudinaryHelper.LoadListAllImages(aFileName: String);
var
 i : Integer;
 aList, aDelim : TStringList;
begin
 ClearList( FGlobalImageList );
 aList   := TStringList.Create;
 aDelim  := TStringList.Create;
 try
   aList.LoadFromFile(aFileName);
   aDelim.Delimiter := '|';
   aDelim.StrictDelimiter := True;

   for i := 0 to pred(aList.Count) do begin
     aDelim.DelimitedText := aList[i];
     if High(FGlobalImageList) < 0 then SetLength(FGlobalImageList ,1) else SetLength(FGlobalImageList ,High(FGlobalImageList)+2);
     new( FGlobalImageList[ High(FGlobalImageList) ] );
       FGlobalImageList[ High(FGlobalImageList) ].FileName := aDelim[3] + aDelim[0];
       if aDelim[1] <> '' then
         FGlobalImageList[ High(FGlobalImageList) ].Width  := aDelim[1].ToInteger;
       if aDelim[2] <> '' then
         FGlobalImageList[ High(FGlobalImageList) ].Height := aDelim[2].ToInteger;

       FGlobalImageList[ High(FGlobalImageList) ].Uri    := aDelim[4];
   end;
 finally
   aDelim.free;
   aList.Free;
 end;
end;

procedure TCloudinaryHelper.LoadListSelectedImages(aFileName: String);
var
 i : Integer;
 aList, aDelim : TStringList;
begin
 ClearList( FSelectedImageList );
 aList   := TStringList.Create;
 aDelim  := TStringList.Create;
 try
   aList.LoadFromFile(aFileName);
   aDelim.Delimiter := '|';
   aDelim.StrictDelimiter := True;

   for i := 0 to pred(aList.Count) do begin
     aDelim.DelimitedText := aList[i];
     if High(FSelectedImageList) < 0 then SetLength(FSelectedImageList ,1) else SetLength(FSelectedImageList ,High(FSelectedImageList)+2);
     new( FSelectedImageList[ High(FSelectedImageList) ] );
       FSelectedImageList[ High(FSelectedImageList) ].FileName := aDelim[3] + aDelim[0];
       if aDelim[1] <> '' then
         FSelectedImageList[ High(FSelectedImageList) ].Width  := aDelim[1].ToInteger;
       if aDelim[2] <> '' then
         FSelectedImageList[ High(FSelectedImageList) ].Height := aDelim[2].ToInteger;

       FSelectedImageList[ High(FSelectedImageList) ].Uri    := aDelim[4];
   end;
 finally
   aDelim.free;
   aList.Free;
 end;
end;

procedure TCloudinaryHelper.MsgDlg(aMsg: String);
var
 i: Integer;
 aFormWidth : Integer;
begin
 with CreateMessageDialog(aMsg, mtInformation, [mbOk], mbOk) do
 try
   Width := 300; //TLabel(Controls[i]).Width * 2;
   aFormWidth := Width;

   for i := 0 to ControlCount - 1 do begin
     if Controls[i] is TLabel then
     begin
       with Controls[i] as TLabel do
       begin
         Font.Name := 'Courier New';
         Font.Size := 10;
         AutoSize  := True;
         WordWrap  := False;
         aFormWidth := Width * 2;
       end;
     end;

     if Controls[i] is TButton then
     begin
       Controls[i].Left := (aFormWidth - Controls[i].Width) div 2;
     end;
   end;
   Width := aFormWidth;
   ShowModal;
 finally
   Free;
 end;
end;

function TCloudinaryHelper.DoSelectImages: boolean;
var
 i : Integer;
begin
 Result := False;
 With Vcl.ExtDlgs.TOpenPictureDialog.Create(nil) do
 begin
   Options := [ Vcl.Dialogs.ofAllowMultiSelect ];
   Filter  := ''
            + 'JPEG    Images (*.JPG)|*.jpg|'
            + 'Bitmap  Images (*.BMP)|*.bmp|'
            + 'GIF       Images (*.GIF)|*.gif|'
            + 'PNG     Images (*.PNG)|*.png|'
            + 'Tümü (*.JPG, *.BMP, *.PNG, *.GIF)|*.jpg;*.bmp;*.png;*.gif|';
   FilterIndex := 4;
   if Execute then
   begin
     ClearList( FSelectedImageList );
     SetLength( FSelectedImageList, Files.count );
     for i := 0 to pred(Files.Count) do begin
       new( FSelectedImageList[i] );
       FSelectedImageList[i].FileName := Files[i];
     end;
     Result := True;
   end;
 end;
end;

function TCloudinaryHelper.DoSendImages: TSentResult;
var
 RCli    : REST.Client.TRESTClient;
 RReq    : REST.Client.TRESTRequest;
 RRes    : REST.Client.TRESTResponse;

 jValue  : SYSTEM.Json.TJSONValue;
 i, successCount, failedcount : Integer;
 API_Upload_BaseUrl : String;
begin
                    // 'https://api.cloudinary.com/v1_1/<cloud name>/<resource_type>/upload';
 API_Upload_BaseUrl := 'https://api.cloudinary.com/v1_1/'+ FAPI_cloud_Name+'/'+ FAPI_resource_Type+'/upload';
 Result := Default(TSentResult);
 if high(FSelectedImageList) < 0  then exit;
 RCli  := REST.Client.TRESTClient.Create( '' );
 RRes  := REST.Client.TRESTResponse.Create( nil );
 RReq  := REST.Client.TRESTRequest.Create ( nil );
 Try
   RCli.BaseURL  := API_Upload_BaseUrl;
   RReq.Method   := REST.Types.rmPOST;
   RReq.Client   := RCli;
   RReq.Response := RRes;
   RReq.Timeout  := 10000;

   successCount  := 0;
   failedcount   := 0;
   for i := Low(FSelectedImageList) to High(FSelectedImageList) do begin
     RReq.Params.Clear;
     RReq.AddParameter('n/a', 'n/a');
     RReq.AddParameter('upload_preset', API_UnsignedUpload_Preset );
     RReq.AddParameter('file', FSelectedImageList[i].FileName, REST.Types.TRESTRequestParameterKind.pkFILE );
     RReq.Execute;

     if RRes.Status.SuccessOK_200 then
     begin
       jValue   := RRes.JSONValue;
       FSelectedImageList[i].Uri := jValue.GetValue<String>('url');
       inc(successCount);

    // *** ListView Section ***
       With TPicture.Create do
       try
         LoadFromFile( FSelectedImageList[i].FileName );
         FSelectedImageList[i].Width   := Width;
         FSelectedImageList[i].Height  := Height;
       finally
         free;
       end;
    // ***
     end else inc(failedcount);
   end; //for
   AddSentImagesToGlobal();
   Result.success := successcount;
   Result.failed  := failedcount;
 finally
   RRes.Free;
   RReq.Free;
   RCli.Free;
 end;
end;

initialization
 xCloudinary := TCloudinaryHelper.Create;

finalization
 FreeAndNil(xCloudinary);

end.
Ellerin dert görmesin @mrmarman Smile
Çok güzel bir çalışma olmuş.

Ben o makaleden beri Cloudinary'i kullanıyorum. Herkese tavsiye ederim...
Hatta Delphi'de eklenti haline getirdim, bir türlü paylaşmak nasip olmadı. Bu vesileyle yakında paylaşırım inşallah Smile
Aynen size katılıyorum.

Forumdaki mesajlara üşenmeden resim / ekran kopyası göndermemi sağlayan tool bu işte.

Bugün de bu sistemi foruma monte etme konusunda ısrarlıyım. Yazılımı aradan çıkartıp php ile direkt gönderip forum hostu rahatlatmak için biçilmiş kaftan.
Benimki de bu:
Delphi ekranında dilediğiniz bir kısmın resmini alıp kaydedebilir yada Cloudinary'ine upload edebilirsiniz. Upload gerçekleştikten sonra da link otomatik olarak clipboard'a kopyalanıyor. Bana sadece linki foruma kopyalamak kalıyor Smile


sonuc_gmxarc.gif
Fikri çok beğendim, yarın ilk iş ekliyorum  Smile
(29-05-2020, Saat: 00:24)SimaWB Adlı Kullanıcıdan Alıntı: [ -> ]Benimki de bu:
Delphi ekranında dilediğiniz bir kısmın resmini alıp kaydedebilir yada Cloudinary'ine upload edebilirsiniz. Upload gerçekleştikten sonra da link otomatik olarak clipboard'a kopyalanıyor. Bana sadece linki foruma kopyalamak kalıyor Smile


sonuc_gmxarc.gif

Konu da açsaydı. Smile
Konu da açsaydı mevzu ilgi çekici olup olmadığı mıdır?
(29-05-2020, Saat: 01:28)engerex Adlı Kullanıcıdan Alıntı: [ -> ]Konu da açsaydı. Smile

Yaptığım Delphi eklentisinin sadece bir kısmı. Diğer kısımlarını tamamlamak bir türlü nasip olmayınca paylaşamadım Sad
Forumda konu da açsaydı şeklinde, benim jeton geç düştü...

@SimaWB bu arada Screen Snapshot kısmını da ekledim.  Smile 


pUVHKIl.gif
(29-05-2020, Saat: 13:40)mrmarman Adlı Kullanıcıdan Alıntı: [ -> ]Forumda konu da açsaydı şeklinde, benim jeton geç düştü...

@SimaWB bu arada Screen Snapshot kısmını da ekledim.  Smile 


pUVHKIl.gif

Merhaba,
Bu gifli paylaşımlar çok güzel ancak gifin başını kaçırınca neresi başı bulmak zor oluyor. Bu giflerin altına uzunca progresbar ve/veya 4/32 (32 saniyelik görüntünün 4. saniyesindesin) gibi bir zaman belirtmek mümkün mü?
Sayfalar: 1 2