PDA

View Full Version : Use Base64 Encode In Delphi



حمید محمودی
یک شنبه 23 خرداد 1389, 23:50 عصر
باسلام،
دوستان کسی یه Demo از این نوع Encoding داره که بشه عکسی که در یه TImage هست رو بریزه توی فایل و دوباره مستقیم بخوندش.
قبلا یه نمونه دیده بودم ولی کار نکرد..
مرسی

vcldeveloper
دوشنبه 24 خرداد 1389, 04:37 صبح
برای Base64 فرقی نمیکنه که شما چی رو باهاش Encode می کنید، میخواید یک تصویر باشه، یا یک صوت، یا یک متن، یا هر داده دیگه ایی؛ Base64 ورودی شما را به عنوان یک مجموعه از بایت ها دریافت میکنه، و آنها را به صورت مجموعه ایی از کارکترهای حرفی Encode میکنه. پس Encode کردن یک تصویر با استفاده از Base64 فرق خاصی با Encode کردن سایر داده ها با آن نداره.

برای کار با Base64 در دلفی، هم می تونید از کدهای ارائه شده برای این منظور در Indy استفاده کنید، هم یک یونیت اوپن سورس با نام SZCodeBaseX هست، که توابع مختلفی برای Encode کردن string, آرایه ایی از بایت ها، یا Stream؛ به Base64 ارائه میکنه.

می تونید خیلی راحت تصویر مورد نظرتان را در یک Stream بریزید، و از Stream با استفاده از یکی از راهکارهای مطرح شده، خروجی Base64 بگیرید.

حمید محمودی
دوشنبه 24 خرداد 1389, 22:15 عصر
برنامه زیر رو ببینید.

اگر روی Encode File کلیک کنیم، میاد فایل JPG رو انکد کرده و میریزه توی فایل txt ؛ بعدشم با کلیک روی Decode File کار رو برعکسی انجام میده.

اگر بخایم متنی که در FileEncrypted.txt هست مستقیم در Image1 نشون بدیم چه باید کرد؟؟؟؟ (نه اینکه بیایم یه فایل ازش بسازیم و بعد اون فایل رو لود کنیم توی TImage)

vcldeveloper
سه شنبه 25 خرداد 1389, 01:33 صبح
اگر بخایم متنی که در FileEncrypted.txt هست مستقیم در Image1 نشون بدیم چه باید کرد؟؟؟؟ (نه اینکه بیایم یه فایل ازش بسازیم و بعد اون فایل رو لود کنیم توی TImage)
به جای TFileStream از TMemoryStream و به جای متدهای LoadFromFile و SaveToFile هم از متدهای LoadFromStream و SaveToStream استفاده کنید.

حمید محمودی
سه شنبه 25 خرداد 1389, 13:21 عصر
متاسفانه متدهای LoadFromFile و SaveToFile رو پیدا پیدا نکردم.
اگه امکانش هست تغییری که گفتین رو روی برنامه اعمال کنید لطفا.



راستی یه سوال دیگه » MIME که در برنامه هست(Height فرم رو یه خورده بیشتر کنید معلوم میشه) کوچک یا بزرگتر بودنش چقدر در سرعت خوندن از فایل و یا احیانا چقدر در نوشتن و انکد کردن تاثیر داره؟؟؟

و اینکه آیا استانداردی براش(منظورم همون مقدار MIME هست) در این نوع انکد هست؟؟ مثلا در بعضی جاها طولش دیدم بزرگتره و در بعضی جاها کوجکتر!!!

مرسی

vcldeveloper
سه شنبه 25 خرداد 1389, 14:00 عصر
متاسفانه متدهای LoadFromFile و SaveToFile رو پیدا پیدا نکردم.
اینها متدهای مربوط به Stream هستند.


راستی یه سوال دیگه » MIME که در برنامه هست(Height فرم رو یه خورده بیشتر کنید معلوم میشه) کوچک یا بزرگتر بودنش چقدر در سرعت خوندن از فایل و یا احیانا چقدر در نوشتن و انکد کردن تاثیر داره؟؟؟

و اینکه آیا استانداردی براش(منظورم همون مقدار MIME هست) در این نوع انکد هست؟؟ مثلا در بعضی جاها طولش دیدم بزرگتره و در بعضی جاها کوجکتر!!!
متوجه منظورتون نشدم.

حمید محمودی
سه شنبه 25 خرداد 1389, 14:25 عصر
متوجه منظورتون نشدم.
فرم اصلی برنامه رو که باز کردید، اگه یه خورده Heightش رو زیاد تر کنید یه Edit هست مربوط به MIME line
عددی که توش مینویسیم تعداد کارکترها (البته اگه درست گفته باشم) مربوط به خطوطی که میخاد دخیره بشه رو مشخص میکنه. میخاستم بدونم کوچک یا بزرگتر بودنش چقدر در سرعت خوندن از فایل و یا احیانا چقدر در نوشتن و انکد کردن تاثیر داره؟؟؟

و اینکه آیا استانداردی براش(منظورم همون مقدار MIME هست) در این نوع انکد هست؟؟ مثلا در بعضی جاها طولش دیدم بزرگتره و در بعضی جاها کوجکتر!!!



اینها متدهای مربوط به Stream هستند.
بله، اما من زیاد با اون آشنایی ندارم،اگه ممکنه زحمتشو بگشید و تغییر رو روی برنامه بدید لطفا....

vcldeveloper
سه شنبه 25 خرداد 1389, 17:55 عصر
عددی که توش مینویسیم تعداد کارکترها (البته اگه درست گفته باشم) مربوط به خطوطی که میخاد دخیره بشه رو مشخص میکنه. میخاستم بدونم کوچک یا بزرگتر بودنش چقدر در سرعت خوندن از فایل و یا احیانا چقدر در نوشتن و انکد کردن تاثیر داره؟؟؟

و اینکه آیا استانداردی براش(منظورم همون مقدار MIME هست) در این نوع انکد هست؟؟ مثلا در بعضی جاها طولش دیدم بزرگتره و در بعضی جاها کوجکتر!!!
لازم نیست شما با MimeLine کار داشته باشید، از همون مقدار پیش فرض آن استفاده کنید. MimeLine در اونجا احتمالا بخاطر تعیین اندازه هر خط در استاندارد MIME هست، که بر طبق اون استاندارد، مقدار معینی نداره، فقط نباید از 76 بیشتر بشه.


اما من زیاد با اون آشنایی ندارم


var
sIn,
sOut : TMemoryStream;
begin
sIn := nil;
sOut := nil;
sIn := TMemoryStream.Create;
sOut:= TMemoryStream.Create;
try
Image1.Picture.Graphic.SaveToStream(sIn);
sIn.Position := 0;
SZEncodeBase64(sIn, sOut);
sOut.Position := 0;
Memo1.Lines.LoadFromStream(sOut);
finally
sIn.Free;
sOut.Free;
end;
end;

کد مربوط به Decode رو هم از روی همین خودتون بنویسید.

حمید محمودی
سه شنبه 25 خرداد 1389, 20:42 عصر
شاید بهتر میبود میگفتم که من اصلا با اون آشنایی ندارم:افسرده:


اما ببینید این کدی که گفتین میاد یه MemoryStream میسازه و بعد عکسی که داخل Image1 هست رو میریزه توی sIn ؟؟ بعدشم دیکدش میکنه؟؟ یا اینکه ... ؟؟؟؟ (من متوجه نشدم)

من نتونستم با کدی که دادین به هدفم برسم.از دوستان کسی اگه وقت کرد لطفا نمونه کدی که آقای کشاورز دادن رو توی برنامه بنویسه و برنامه رو آپلود بکنه ممنون میشم!! (من میخام با کلیک روی دکمه Encode عکس رو انکد بکنه و بریزه توی فایل FileEncrypted --که اینکارو به درستی انجام میده-- بعد با کلیک روی Decode محتوای همین فایل متنی رو مستقیم دیکد کنه و توی Image1 بزاره --که همین کار مونده فقط)

تشکر

vcldeveloper
چهارشنبه 26 خرداد 1389, 00:27 صبح
اما ببینید این کدی که گفتین میاد یه MemoryStream میسازه و بعد عکسی که داخل Image1 هست رو میریزه توی sIn ؟؟ بعدشم دیکدش میکنه؟؟ یا اینکه ... ؟؟؟؟ (من متوجه نشدم)
کد بالا تصویر موجود در Image1 رو Encode میکنه و نتیجه رو در Memo1 میریزه. برای Decodeاش هم باید همین مراحل را طی کنید، فقط جای Image1 و Memo1 عوض میشه.

حالا اگر شما میخواید نتیجه Encode به جای Memo1 در یک فایل ذخیره بشه، از همون کد بالا می تونید استفاده کنید، با این تفاوت که به جای انتقال مقدار sOut به Memo1، مقدر sQut را با استفاده از متد SaveToFile آن، در یک فایل ذخیره کنید.
برای Decode از فایل هم، به جای خط مربوط به Image1، بنویسید sIn.LoadFromFile، و نام فایل خودتان را قید کنید.

کار کردن با Stream کار پیچیده ایی نیست، توی Help دلفی درباره Stream و متدهای هر کدام از این کلاس ها هم توضیحات زیادی داده شده، هم مثال هایی ارائه شده.

حمید محمودی
چهارشنبه 26 خرداد 1389, 02:23 صبح
کارایی که گفتین رو انجام دادم. اما در حالت زیر Error میده.(مثلا بخایم اون متنی که در Memo انکد شده رو در Image2 دیکد کرده و نمایش بدیم. )



var
sIn,
sOut : TMemoryStream;
begin
sIn := nil;
sOut := nil;
sIn := TMemoryStream.Create;
sOut:= TMemoryStream.Create;
try
Memo1.Lines.SaveToStream(sIn);
sIn.Position := 0;
SZDecodeBase64(sIn, sOut);
sOut.Position := 0;
Image2.Picture.Graphic.LoadFromStream(sout);
finally
sIn.Free;
sOut.Free;
end;
اگه در کد بالا به جای Image2 بنویسم Image1 ارور نمیده اما ظاهرا کاری هم انجام نمیده!!!

همین حالت برای فایل هم هست. یعنی اگه در کد زیر بنویسم Image2 بازم همون ارور Access Validation رو میده. اما در حالت زیر چون توی Image1 تصویر هست ارور نمیده!! (همون تصویری که توی Image1 هست و انکدش کردیم....)



var
sIn,
sOut : TMemoryStream;
begin
sIn := nil;
sOut := nil;
sIn := TMemoryStream.Create;
sOut:= TMemoryStream.Create;
try
sIn.LoadFromFile('FileEncrypted.txt') ;
sIn.Position := 0;
SZDecodeBase64(sIn, sOut);
sOut.Position := 0;
Image1.Picture.Graphic.LoadFromStream(sOut);
finally
sIn.Free;
sOut.Free;
end;
کدها درستن؟؟ چکار بکنم؟؟

مرسی

vcldeveloper
چهارشنبه 26 خرداد 1389, 05:43 صبح
اگه در کد زیر بنویسم Image2 بازم همون ارور Access Validation رو میده. اما در حالت زیر چون توی Image1 تصویر هست ارور نمیده!!
به خاطر اینکه خصوصیت Graphics اون Image نباید خالی باشه؛ اگر در Image تصویری نباشه، یعنی خصوصیت Graphics اون nil هست، پس اجرای متد های آن امکان پذیر نیست.

این دیگه به Base64 مربوط نمیشه، بلکه به کامپوننت TImage دلفی، و پیاده سازی آن مربوط میشه. می تونید به جای خصوصیت Graphic، از خصوصیت Bitmap استفاده کنید.

حمید محمودی
چهارشنبه 26 خرداد 1389, 16:02 عصر
می تونید به جای خصوصیت Graphic، از خصوصیت Bitmap استفاده کنید.
یعنی اینطوری دیگه؟؟



Image2.Picture.Bitmap.LoadFromStream(sout);
فرض کنید نمیدویم که کاربری که تصویر رو انکد میکنه فرمتش چیه؟ الان که از خاصیت Bitmap استفاده کردیم، من اگه یه تصویر JPG رو انکد بکنم ، موقع دیکدش میگه not bitmap image invalid و ارور میده...

همچنین برای فرمت های دیگه چکار باید کرد...؟؟؟

vcldeveloper
چهارشنبه 26 خرداد 1389, 18:17 عصر
برای فرمت های دیگه چکار باید کرد...؟؟؟
TImage برای نمایش صحیح تصاویر فرمت های مختلف، وابسته به پسوند فایل تصویری هست. پس اگر بخواید از TImage استفاده کنید، یا باید از قبل فرمت تصویری مربوطه رو بشناسید، و بر اساس آن، از کلاس مشتق شده از TGraphic که مناسب آن فرمت هست (مثلا TJpegImage برای JPEG) استفاده کنید؛ یا اینکه باید خودتون بایت های Decode شده را آنالیز کنید، و فرمت تصویری را تشخیص بدید، و بر اساس آن، از کلاس مناسب استفاده کنید.

حمید محمودی
چهارشنبه 26 خرداد 1389, 20:18 عصر
یا اینکه باید خودتون بایت های Decode شده را آنالیز کنید، و فرمت تصویری را تشخیص بدید، و بر اساس آن، از کلاس مناسب استفاده کنید.


اینکار فکر کنم دیگه سخت میشه.. چون خیلی جاها دیدم که میان نوع فایلی که انکد شده رو هم مینویسن توی فایل. مثلا برای کارت ویزیت ویندوز .vcf یه همچین چیزیه (البته اگه تصویر رو JPG اد کنیم توش)



PHOTO;TYPE=JPEG;ENCODING=BASE64


منم میخام همین کار بالایی رو انجام بدم. که احتمالا راهش همینی هست که در پایین گفتین :



یا باید از قبل فرمت تصویری مربوطه رو بشناسید، و بر اساس آن، از کلاس مشتق شده از TGraphic که مناسب آن فرمت هست (مثلا TJpegImage برای JPEG) استفاده کنید


مثلا یه دکمه گذاشتیم در برنامه و کاربر میاد روش کلیک میکنه و یه تصویر رو (که معلوم نیست فرمتش چیه) انتخاب میکنه. بعد میاد اونو انکد میکنه و میریزه داخل فایل یا همون Memo1 (با دکمه انکد در برنامه)

موقع دیکد کردن اگه گفته باشم :



Image2.Picture.Bitmap.LoadFromStream(sout);

در اینجا اگه تصویری که انکد شده Bitmap باشه خوب حله و مشکلی نیست.

اما اگه با فرمت دیگه باشه اروری که عرض کردم رو میده. چکار باید بکنم؟؟ و چطوری بفهمم که فرمت چیه تا موقع دیکد مشکلی نداشته باشم. (درمورد اون کلاس مشتق کردن از TGraphic متوجه نشدم چکار باید بکنم)

و اینکه آیا یعد از اینکه فهمیدم فرمت فایل تصویری چیه باید بیام باز از کد زیر استفاده کنم


Image2.Picture.Bitmap.LoadFromStream(sout);


یا این کد زیر : (اگه این کد زیر باشه که باز باید یه تصویر داخل Image باشه تا بشه از این خصوصیت استفاده کرد که!!)


Image2.Picture.Graphic.LoadFromStream(sout);


تشکر

vcldeveloper
پنج شنبه 27 خرداد 1389, 00:01 صبح
چطوری بفهمم که فرمت چیه تا موقع دیکد مشکلی نداشته باشم.
در پست قبلی توضیح دادم.


درمورد اون کلاس مشتق کردن از TGraphic متوجه نشدم چکار باید بکنم
وقتی نوع تصویر مشخص شد، می تونید یک شی از کلاس مربوط به اون تصویر ایجاد کنید، و به خصوصیت Graphic اون TImage بدید، و متن مورد نظر را در آن Decode کنید. مثلا اگر مشخص شد که تصویر مربوطه JPEG هست:


var
NewImage : TJpegImage;
begin
NewImage := TJPEGImage.Create;
try
Image1.Picture.Graphic.Assign := NewImage;
/// Here you can decode the data into Image1.Picture.Graphic
finally
NewImage.Free;
end;
end;

تجلی
جمعه 30 دی 1390, 17:25 عصر
من برای اینکود کردن یه متن با استفاده از IdEncoderMime با راهنمایی که آقای کشاورز در این پست انجام دادند به این شکل عمل کردم و ظاهرا درست اینکود شد >


procedure TForm1.Button1Click(Sender: TObjectprocedure TForm1.Button1Click(Sender: TObject);
var filein,fileout:TMemoryStream;
begin
filein :=nil;
fileout:=nil;
filein:=TMemoryStream.Create;
fileout:=TMemoryStream.Create;

memo1.Lines.SaveToStream(filein);
filein.Position:=0;
IdEncoderMime.Encode(filein,fileout);
fileout.Position:=0;
memo2.Lines.LoadFromStream(fileout);
filein.Free;
fileout.Free
end;
البته پارامتر سوم رو در این خط متوجه نشدم چیه و نزاشتم ولی درست عمل کرد اگر میدونید چیه ممنون میشم توضیح بدید اولی فایل ورودی دومی فایل خروجی اما سومی چیه !؟ .
>
encoder.Encode(sin,sout, ????);

اما برای decode کردن از IdDecoderMime استفاده کردم ولی خروجی که بهم میده چند تا علامت سواله ! چطور میتونم این متن فارسی رو درست نشون بدم ؟ بدون تغییر تنظیمات مربوط به زبان در سیستم عامل . (non unicode language )