حفظ ملفات PDF (أو أي ملف آخر) في قاعدة البيانات MySQL باستخدام JAVA
بسم الله الرحمن الرحيم
السلام عليكم ورحمة الله وبركاته
بعد غيبة طويلة أعود بموضوع صغير نوعاً ما لكنه ذي فائدة كبيرة.
في هذا الموضوع إن شاء الله سنتعرض لطريقة حفظ وفتح ملفات PDF (سأستخدم pdf في المثال لكن في الحقيقة بالامكان حفظ أي نوع من أنواع الملفات سواء ملفات صوتية أو صور أو فيديو).
يجب أن يكون القارء ملم ببعض الأساسيات بكيفية ربط قاعدة البيانات (MySQL) مع ملف Java كذلك كيفية التعامل مع قاعدة البيانات من إنشاء، استعراض واضافات البيانات داخل قاعدة البيانات . وإن شاء الله سأوفر كل الموارد التي نحتاجها في موضوعنا هذا. بسم الله نبدأ.
- هل حفظ الملفات داخل قاعدة البيانات الطريقة الوحيدة؟
بالطبع حفظ الملفات داخل قاعدة البيانات ليست الطريقة الوحيدة لحفظ الملفات داخل الخادم بل هناك طرق أخرى، مثلا يمكنك أن تحفظ الملفا داخل أي مكان في الخادم ومن ثم تحفظ المسار الكامل له داخل قاعدة البيانات، وقد يحبب الكثير هذه الطريقة؛ لكن لحفظ الملفات داخل قاعدة البيانات محاسنها (كما ولها مساوئها) فمثلاً في حال أردت أخد نسخة احتياطية لبياناتك ليس عليك سوى أخذ نسخة من قاعدة البيانات نفسها بدون نسخ أي ملفات أخرى، قد تضطر لتغيير مكان الملفات في مرحلة ما وفي هذه الحال يجب عليك أن تغيير المسار المحفوظ للملف داخل قاعدة البيانات (لا أقول بأن هذا صعب لكنه يحتاج إلى وقت)، كذلك فإن بياناتك محمية من الدخول أو الحذف أو التغيير غير المصرح به بما أنها داخل قاعدة البيانات. من العيوب التي قد تمنعك من حفظ الملفات داخل قاعدة البيانات هو الحجم المهول الذي ستقدوا عليه بعد فترة من الزمن، لكن لا أعتقد بأن هذا ذي أهمية كبيرة حيث أنك تريد المحافظة على كل بياناتك من الضياع فعند نسخك أو أخذك نسخة احتياطية لقاعدة البيانات فإنك تريد الحفاظ على الملفات كذلك ولكن لحل هذه المشكلة بالامكان حفظ الملفات داخل جدول مستقل لإقصائها من بعض العمليات.
- ما هي الملفات التي تقبل قاعدة البيانات حفظها؟
قاعدة البيانات تحفظ الملفات على شكل ملف Binary (ثنائي) كبير؛ بالتالي فإن قاعدة البيانات قاددرة على حفظ أي نوع من أنواع الملفات مهما كان ملفات الفيديو مثل mp4. أو .mkv، ملفات الصوت مثل ,aac أو .m4a، الصور بشتى أنواعها أو المفات المكتبية. ببساطة أي ملف يمكن تخيله باستطاعتنا حفظه داخل قاعدة البيانات.
- ما هو أقصى حجم للملف؟
قواعد البيانات MySQL تحتوي على أربع أنواع يمكن حفظ الملفات فيها، ما يمز كل نوع عن الآخر هو أقصى حجم يمكن حفظها دخلها فقط، أما طريقة التعامل معها في الحفظ والاسترجاع فمتماثله.
1. TINYBLOB: أقصى حجم هو (28 ما يعادل 256 بايت).
2. BLOB: أقصى حجم هو (216 ما يعادل 65 كيلوبايت).
3. MEDIUMBLOB: أقصى حجم هو (224 ما يعادل 16 ميجابايت).
4. LONGBLOB: أقصى حجم هو (232 ما يعادل 4 جيجابايت).
يعتمد على أقصى حجم تحتاجه لحفظ الملف مثلا ملفات الصوت لن يتعدى حجم الملف الواحد في أسوء الأحوال 16 ميغا، ففي هذه الحالة سأختار نوع MEDIUMBLOB، أما لو كنت أحتاج مساحة أكبر أو أصغر فهنا سأختار غيره من الأنواع.
- الأدوات والبرامج المستخدمة:
- سيرفر قاعدة بيانات MySQL (بالإمكان استخدام XAMPP أو SQLite)
-ملف jar والذي يربط قاعدة البيانات بمشروع Java. (متوفر في المرفقات نسخة 5.1.44 mysql-connector-java-5.1.44.zip)
على فرض بأنك قاعد على ربط ملف jar بمشروعك في Java سوف أكمل الشرح.
خطوات العمل:
أولاً: إنشاء جدول في قاعدة البيانات:
سنقوم بإن شاء ملف داخل قاعدة البيانات لنحفظ بداخله اسم الملف، ونوعه ( The file name extension).
إذا الجدول (باسم myData) يحتوي على 4 أعمدة، رقم الملف (id), اسم الملف(fullname), نوع الملف (type), الملف (file):
CREATE TABLE myData(id INT(11) NOT NULL PRIMARY KEY,
fullname VARCHAR(35)NOT NULL,
type VARCHAR(8) NOT NULL,
file MEDIUMBLOB NOT NULL);
ثانياً: حفظ ملف باستخدام Java:
الآن انتهى عملنا داخل قاعدة البيانات وننتقل إلى Java وسنقوم بانشاء class نقوم بتسميته storeData, ونقوم بإنشاء العمليات الازمة بربطه بقاعدة البيانات:
try {
Class.forName("com.mysql.jdbc.Driver");
Connection connect = DriverManager.getConnection("jdbc:mysql://localhost/pro3alam","root", "");
} catch (SQLException e) {}
catch (Exception e) {}
بعد ذلك نجهز اوجكت من نوع PreparedStatement لنقوم باطلاق كود MySQL من خلاله:
PreparedStatement preStat = connect.prepareStatement("INSERT INTO myData VALUES(?, ?, ?, ?)");
بعد ذلك نقوم بإنشاء ملف ونحدد موقع الملف الذي نريد حفظه لنفرض بأن الملف في سطح المكتب باسم test ونوع pdf ونقوم بحفظ اسمه ونوعه في متغيرين مختلفين كالتالي:
File myFile = new File("/Users/abather/Desktop/test.pdf");
String fileName = myFile.getName().substring(0, myFile.getName().lastIndexOf("."));
String fileType = myFile.getName().substring(myFile.getName().lastIndexOf("."),
myFile.getName().length());
للتفصيل أكثر في الأكواد السابقة فقد قمت بحفظ اسم الملف داخل المتغيير fileName عن طريق اخذ الجزء من بداية الاسم الى آخر نقطة أي قبل نوع الملف.
ومن ثم قمت بحفظ نوع الملف داخل المتغيير fileType عن طريق اخذ الجزء من اسم الملف الذي يبدأ بآخر نقطة الى نهاية الاسم.
من الآفضل حفظ نوع الملف على حدى عن اسم الملف في حال أردت تغيير الاسم أو حفظ أكثر من نوع واحد من الملفات داخل نفس الجدول.
الآن ننتقل إلى النقطة ما قبل الأخيرة وهي بتجهيز الملف ليتم كتابته داخل القاعدة، ونقوم بتجهيزية عن طريق FileInputStream كما يوضح الكود التالي:
FileInputStream inputstream = new FileInputStream(myFile);
الآن اصبح الملف جاهزة لكتابته دخل قاعدة البيانات، نعود الى PreparedStatement التي قمنا بانشائها ونقوم بادخال البيانات التي نريد حفظها ومن ثم نقوم باطلاقها للكتابة داخل قاعدة البيانات كما يوضح الكود التالي:
FileInputStream inputstream = new FileInputStream(myFile);
preStat.setInt(1, 1);
preStat.setString(2,fileName);
preStat.setString(3,fileType);
preStat.setBinaryStream(4,inputstream, inputstream.available());
preStat.execute();
كما هو واضح في الكود فقد اتممت اضافة القيم الى كل عامو في الجدول من رقم الملف واسمه ونوعه والملف نفسه.
ويجب الحذر بأن نوع الميثود المستخدمة لكتابة الملفات هي setBinaryStream. وفي نهاية الكود بعد اطلاق PreparedStatement نكون قد حفظنا الملف داخل قاعدة البيانات.
نعود لقاعدة البيانات ونبحث عن الملف لنتأكد من وجوده:
ملاحظة: لا تحاول البحث عن الملف في حال كنت في Terminal لانه لن يكون سوى مجموعة من الرموز غير المفهومه.
ثالثا: قراءة الملف المحفوظ داخل قاعدة البيانات:
هنا سنقوم بقراءة الملف السابق من قاعدة البيانات وحفظه على سطح المكتب، في البداية سنقوم بانشاء class باسم restoreData.
سنقوم بالخطوات السابقة بالاتصال بقاعدة البيانات، ومن ثم نقوم بإنشاء Statement والبحث عن الصف الذي حفظنا الملف بداخله وتخزينه داخل ResultSet كالتالي:
Statement statement = connect.createStatement();
ResultSet result = statement.executeQuery("SELECT * FROM myData WHERE id=1");
الان سنقوم بحفظ اسم الملف ونوعه داخل متغير واحد مع تغير بسيط في الاسم ومن ثم إن شاء ملف File وجعل مساره يشير الى سطح المكتب كالتالي:
result.next();
String fullName = result.getString(2) + "From DB" + result.getString(3);
//سيكون هذا اسم الملف الذي سنسترده من قاعدة البيانات
//بالامكان تغيير الاسم كيفما نريد ولكن المهم هو نوع الملف
File myFile = new File("/Users/abather/Desktop/"+fullName);
الان نقوم بانشاء اوبجكت من نوع FileOutputStream والذي سيقوم بكتابة البيانات داخل الملف ومن ثم حفظه على سطح المكتب، كذلك نحن بحاجة لمتغير من نوع Inputstream لحفظ البيانات من داخل الناتج من قاعدة البيانات وآخر من نوع byte والذي سيكون بمثابة المكان الذي سنخزن فيه البيانات مؤقتاً لكتابتها داخل الملف :
FileOutputStream outputStream = new FileOutputStream(myFile);
InputStream inputStream = result.getBinaryStream(4);
byte[] buffer = new byte[1024];
while (inputStream.read(buffer) > 0) {
outputStream.write(buffer);
}
هكذا نكون قد قمنا بحفظ الملف واسترجاعه من قاعدة البيانات.
أسأل الله العلي العظيم أن أكون قد وفقت لإصال المعلومة بشكل مبسط وسلس.
واي استفسار حول الموضوع أنا بالخدمة. كذلك السورس كود تجدونه في المرفقات لحفظ واسترجاع الملفات من قاعدة البيانات.
لايوجد لديك حساب في عالم البرمجة؟
تحب تنضم لعالم البرمجة؟ وتنشئ عالمك الخاص، تنشر المقالات، الدورات، تشارك المبرمجين وتساعد الآخرين، اشترك الآن بخطوات يسيرة !