مقدمة
يقوم تطبيق الويب الخاص بي بتخزين البيانات في
localStorage
. كان هذا مناسبًا حتى أردت أن يرى المستخدم نفس الشيء عند الوصول إلى الموقع من أجهزة مختلفة. وهذا هو ، كان مطلوبا التخزين عن بعد.
لكن التطبيق "مستضاف" على صفحات جيثب ولا يحتوي على جزء خادم. قررت عدم إنشاء خادم ، ولكن لتخزين البيانات مع طرف ثالث. وهذا يعطي مزايا كبيرة:
- لا حاجة لدفع ثمن الخادم ، فإنه لا يضر الرأس حول استقراره وتوافره.
- رمز أقل ، أخطاء أقل.
- لا يحتاج المستخدم للتسجيل في طلبي (هذا أمر مزعج للكثيرين).
- الخصوصية أعلى ، ويعرف المستخدم أن بياناته مخزنة في مكان يثق فيه أكثر مني على الأرجح.
أولاً ، وقع الاختيار على
remoteStorage.js . إنها توفر بروتوكولًا مفتوحًا لتبادل البيانات ، وواجهة برمجة تطبيقات جميلة ، والقدرة على الاندماج مع Google Drive و Dropbox ، وكذلك خوادمهم. لكن تحول هذا المسار إلى طريق مسدود (لماذا - قصة منفصلة).
في النهاية ، قررت استخدام Google Drive مباشرةً ،
ومكتبة عميل واجهة برمجة تطبيقات Google (المشار إليها فيما يلي باسم GAPI) كمكتبة للوصول إليها.
لسوء الحظ ، فإن وثائق Google مخيبة للآمال ، ومكتبة GAPI تبدو غير مكتملة ، علاوة على ذلك ، لديها العديد من الإصدارات ، وليس من الواضح دائمًا أي من الإصدارات قيد البحث. لذلك ، يجب جمع حل مشاكلي في أجزاء من الوثائق والأسئلة والأجوبة على StackOverflow والمنشورات العشوائية على الإنترنت.
آمل أن يوفر لك هذا المقال وقتًا إذا قررت استخدام Google Drive في تطبيقك.
التحضير
فيما يلي وصف لكيفية الحصول على مفاتيح للعمل مع Google API. إذا لم تكن مهتمًا ، فانتقل مباشرةً إلى الجزء التالي.
تلقي المفاتيحفي Google Developer Console ،
أنشئ مشروعًا جديدًا ، وأدخل اسمًا.
في "لوحة التحكم" ، انقر على "تمكين API والخدمات" وقم بتشغيل Google Drive.
بعد ذلك ، انتقل إلى واجهة برمجة التطبيقات والخدمات -> قسم بيانات الاعتماد ، انقر فوق "إنشاء بيانات اعتماد". هناك ثلاثة أشياء تحتاج إلى القيام بها:
- تكوين "نافذة طلب وصول OAuth". أدخل اسم التطبيق ونطاقك في قسم "المجالات المعتمدة" ورابطًا إلى الصفحة الرئيسية للتطبيق. الحقول الأخرى اختيارية.
- في قسم "بيانات الاعتماد" ، انقر فوق "إنشاء بيانات اعتماد" -> "معرف عميل OAuth". حدد نوع "تطبيق الويب". في نافذة الإعدادات ، أضف "مصادر Javascript المسموح بها" و "عناوين URL المسموح بها لإعادة التوجيه":
- المجال الخاص بك (مطلوب)
http://localhost:8000
(اختياري للعمل محليا).

- في قسم "بيانات الاعتماد" ، انقر فوق "إنشاء بيانات اعتماد" -> "مفتاح API". في الإعدادات الرئيسية ، حدد القيود:
- نوع التطبيق المسموح به -> الإحالات HTTP (المواقع)
- اقبل طلبات HTTP من مصادر الإحالة (المواقع) التالية -> المجال والمضيف المحلي (كما في النقطة 2).
- واجهات برمجة تطبيقات صالحة -> Google Drive API

يجب أن يبدو قسم بيانات الاعتماد كالتالي:

هنا انتهينا. نمرر الى الكود
التهيئة وتسجيل الدخول
طريقة Google الموصى بها لتمكين GAPI هي لصق الشفرة التالية في HTML الخاص بك:
<script src="https://apis.google.com/js/api.js" onload="this.onload=function(){}; gapi.load('client:auth2', initClient)" onreadystatechange="if (this.readyState === 'complete') this.onload()"> </script>
بعد تحميل المكتبة ، سيتم استدعاء وظيفة
initClient
، والتي يجب أن نكتب أنفسنا. مظهره النموذجي هو كما يلي:
function initClient() { gapi.client.init({
لتخزين البيانات سوف نستخدم ما يسمى
مجلد بيانات التطبيق . مزاياه على مجلد عادي:
- لا يرى المستخدم ذلك مباشرةً: الملفات منه لا تسد مساحته الشخصية ، ولا يمكنه تدمير بياناتنا.
- التطبيقات الأخرى لا تراها ولا يمكنها إفسادها أيضًا.
- النطاق ، المذكور أعلاه ، يمنح التطبيق إمكانية الوصول إليه ، لكنه لا يمنح حق الوصول إلى بقية ملفات المستخدم. أي أننا لن نخيف أي شخص عن طريق طلبات الوصول إلى بياناته الشخصية.
عند التهيئة الناجحة لواجهة برمجة تطبيقات Google ، تقوم الوظيفة بما يلي:
- يبدأ في متابعة أحداث تسجيل الدخول / الخروج - على الأرجح ، يجب أن يتم ذلك دائمًا.
- تهيئة التطبيق. يمكن القيام بذلك قبل تحميل GAPI وتهيئته - كما تفضل. كان إجراء التهيئة مختلفًا قليلاً إذا كانت Google غير متوفرة. قد يقول شخص ما أن هذا لا يحدث :) ولكن ، أولاً ، يمكنك أن تكون ذكيًا بالمفاتيح وحقوق الوصول في المستقبل. ثانياً ، على سبيل المثال ، في الصين ، تم حظر Google.
يتم تسجيل الدخول والخروج ببساطة:
function isGapiLoaded() { return gapi && gapi.auth2 } function logIn() { if (isGapiLoaded()) {
سوف تتلقى نتائج تسجيل الدخول في معالج
onSignIn
:
function isLoggedIn() { return isGapiLoaded() && gapi.auth2.getAuthInstance().isSignedIn.get() } function onSignIn() { if (isLoggedIn()) {
لسوء الحظ ، العمل مع الملفات ليس واضحًا جدًا.
مساعد الوعد
لا يُرجع GAPI الوعود العادية. بدلاً من ذلك ، يتم استخدام واجهة Thennable الخاصة به ، والتي تشبه الوعود ، ولكن ليس تمامًا. لذلك ، لتوفير الراحة للعمل (بشكل أساسي لاستخدام
async/await
) ، سنقوم بعمل مساعد صغير:
function prom(gapiCall, argObj) { return new Promise((resolve, reject) => { gapiCall(argObj).then(resp => { if (resp && (resp.status < 200 || resp.status > 299)) { console.log('GAPI call returned bad status', resp) reject(resp) } else { resolve(resp) } }, err => { console.log('GAPI call failed', err) reject(err) }) }) }
تأخذ هذه الوظيفة طريقة GAPI والمعلمات إليها كوسيطة أولى وتقوم بإرجاع وعد. ثم سترى كيفية استخدامه.
العمل مع الملفات
يجب أن تتذكر دائمًا أن
اسم الملف على Google Drive ليس فريدًا . يمكنك إنشاء أي عدد من الملفات والمجلدات بنفس الاسم. المعرف هو الوحيد الفريد.
بالنسبة للمهام الأساسية ، لا تحتاج إلى العمل مع المجلدات ، لذلك تعمل جميع الوظائف أدناه مع الملفات الموجودة في جذر مجلد Application Data. تشير التعليقات إلى ما يجب تغييره للعمل مع المجلدات. الوثائق من جوجل هنا .
إنشاء ملف فارغ
async function createEmptyFile(name, mimeType) { const resp = await prom(gapi.client.drive.files.create, { resource: { name: name,
تقوم هذه الوظيفة غير المتزامنة بإنشاء ملف فارغ وإرجاع معرفها (السلسلة). إذا كان هذا الملف موجودًا بالفعل ، فسيتم إنشاء ملف جديد بنفس الاسم وسيتم إرجاع معرفه. إذا كنت لا تريد ذلك ، يجب عليك أولاً التحقق من عدم وجود ملف يحمل نفس الاسم (انظر أدناه).
Google Drive ليست قاعدة بيانات كاملة. على سبيل المثال ، إذا كنت تريد أن يعمل عدة مستخدمين من نفس حساب Google في وقت واحد من أجهزة مختلفة ، فقد تكون هناك مشاكل في حل التعارضات بسبب نقص المعاملات. لهذه المهام ، من الأفضل عدم استخدام Google Drive.
العمل مع محتويات الملف
لا يوفر GAPI (لجافا سكريبت المستند إلى المستعرض) طرقًا للعمل مع محتويات الملفات (غريب جدًا ، أليس كذلك؟). بدلاً من ذلك ، هناك طريقة
request
عامة (غلاف رفيع عبر طلب أجاكس بسيط).
من خلال التجربة والخطأ ، توصلت إلى التطبيقات التالية:
async function upload(fileId, content) {
ملف البحث
async function find(query) { let ret = [] let token do { const resp = await prom(gapi.client.drive.files.list, {
هذه الوظيفة ، إذا لم تقم بتحديد
query
، فتُرجع جميع الملفات الموجودة في مجلد التطبيق (صفيف من الكائنات ذات حقول
id
name
) ، مرتبة حسب وقت الإنشاء.
إذا حددت سلسلة
query
(يتم وصف بناء الجملة
هنا ) ، فسوف يعرض فقط الملفات التي تطابق الاستعلام. على سبيل المثال ، لمعرفة ما إذا كان هناك ملف باسم
config.json
، ما عليك القيام به
if ((await find('name = "config.json"')).length > 0) {
حذف الملفات
async function deleteFile(fileId) { try { await prom(gapi.client.drive.files.delete, { fileId: fileId }) return true } catch (err) { if (err.status === 404) { return false } throw err } }
هذه الوظيفة تحذف الملف بمعرف وتُرجع بشكل
true
إذا تم حذفه بنجاح ،
false
إذا لم يكن هناك مثل هذا الملف.
مزامنة
من المستحسن أن يعمل البرنامج في المقام الأول مع
localStorage
، ولا يستخدم Google Drive إلا لمزامنة البيانات من
localStorage
.
التالي هو استراتيجية مزامنة التكوين بسيطة:
- يتم تنزيل التكوين الجديد من Google Drive مع تسجيل الدخول ، ثم كل 3 دقائق ، الكتابة فوق النسخة المحلية ؛
- يتم سكب التغييرات المحلية على Google Drive ، الكتابة فوق ما كان هناك ؛
fileID
التخزين المؤقت fileID
التخزين المؤقت في localStorage
لتسريع العمل وتقليل عدد الطلبات ؛- تكون الحالات (الخاطئة) التي يتم التعامل معها بشكل صحيح عندما يكون لدى Google Drive العديد من ملفات التكوين ، وعندما يقوم شخص ما بحذف ملف التكوين الخاص بنا أو تدميره.
- لا تؤثر تفاصيل المزامنة على باقي رمز التطبيق. للعمل مع التكوين ، يمكنك استخدام وظيفتين فقط:
getConfig()
و saveConfig(newConfig)
.
في تطبيق حقيقي ، ربما تحتاج إلى تطبيق معالجة تعارض أكثر مرونة عند تحميل / إلغاء تحميل التكوين.
الخاتمة
يبدو لي أن مخزن البيانات لموقع ويب على Google Drive رائع للمشاريع الصغيرة والنماذج الأولية. ليس فقط من السهل التنفيذ والدعم ، ولكن أيضًا يساعد على تقليل عدد الكيانات غير الضرورية في الكون. وآمل أن يساعدك مقالتي في توفير الوقت إذا اخترت هذا المسار.
ملاحظة: رمز المشروع الحقيقي
يكمن في جيثب ،
يمكنك تجربته
هنا .