الفرق بين المراجعتين لصفحة: «Cordova/cordova plugin file»

من موسوعة حسوب
لا ملخص تعديل
لا ملخص تعديل
 
(14 مراجعة متوسطة بواسطة 3 مستخدمين غير معروضة)
سطر 1: سطر 1:
<noinclude>{{DISPLAYTITLE:إضافة الوصول إلى الملفات في كوردوفا}}</noinclude>
<noinclude>{{DISPLAYTITLE:إضافة الوصول إلى الملفات في كوردوفا}}</noinclude>
[[تصنيف: Cordova]]
[[تصنيف: Cordova]]
[[تصنيف: plugin]]
[[تصنيف: Cordova Plugin]]
[[تصنيف: cordova-plugin-file]]
تقدم إضافة الملفات (cordova-plugin-file) واجهة برمجية للملفات، والتي يمكن استخدامها للقراءة أو الكتابة في الملفات الموجودة على الجهاز.  
تقدم إضافة الملفات (<code>cordova-plugin-file</code>) واجهة برمجية للملفات، والتي يمكن استخدامها للقراءة أو الكتابة في الملفات الموجودة على الجهاز.


هذه الإضافة مبنية على عدة مواصفات، بما فيها:   
هذه الإضافة مبنية على عدة مواصفات، منها:   
* [http://www.w3.org/TR/FileAPI/ الواجهة البرمجية للملفات في HTML5].
* المجلدات ونظام الملفات بُنِيا على [http://www.w3.org/TR/2012/WD-file-system-api-20120417/ هذه المواصفات]. لكن تجدر الإشارة إلى أن معظم شيفرة الإضافة كُتِبت وفق [http://www.w3.org/TR/2011/WD-file-system-api-20110419/ مواصفات سابقة].
* تعتمد  هذه الإضافة مواصفات الكائن [http://dev.w3.org/2009/dap/file-system/file-writer.html FileWriter]: ‏
'''ملاحظة''': رغم أن مواصفات W3C FileSystem صارت مُتجاوزة في متصفحات الويب، إلا أنّ كوردوفا تدعمها في هذه الإضافة في المنصات المدرجة في فقرة المنصات المدعومة، باستثناء المتصفحات (Browser).


لفهم كيفية استخدام هذه الإضافة، تحقق من المثال في أسفل هذه الصفحة. ولمزيد من الأمثلة (المرتكزة على المتصفحات)، يمكنك الاطلاع على هذا ا[http://www.html5rocks.com/en/tutorials/file/filesystem/ لمقال الرائع حول FileSystem] .  
{{Course|course=javascript}}
__TOC__
*[http://www.w3.org/TR/FileAPI/ الواجهة البرمجية للملفات في HTML5].
* ملحقات المجلدات ونظام الملفات بُنِيا على [http://www.w3.org/TR/2012/WD-file-system-api-20120417/ هذه المواصفات]. لكن تجدر الإشارة إلى أن معظم شيفرة الإضافة كُتِبت وفق [http://www.w3.org/TR/2011/WD-file-system-api-20110419/ مواصفات سابقة].
* كٌتبت شيفرة هذه الإضافة وفق [http://www.w3.org/TR/2011/WD-file-system-api-20110419/ مواصفات سابقة.]
* تعتمد  هذه الإضافة مواصفات الكائن [http://dev.w3.org/2009/dap/file-system/file-writer.html FileWriter]: ‏
'''ملاحظة''': رغم أن مواصفات W3C FileSystem أصبحت مهملة في متصفحات الويب، إلا أنّ كوردوفا تدعمها عبر هذه الإضافة في المنصات المدرجة في فقرة [[Cordova/cordova plugin file#.D8.A7.D9.84.D9.85.D9.86.D8.B5.D8.A7.D8.AA .D8.A7.D9.84.D9.85.D8.AF.D8.B9.D9.88.D9.85.D8.A9|المنصات المدعومة]]، باستثناء المتصفحات (Browser).
 
لفهم كيفية استخدام هذه الإضافة، تحقق من المثال في أسفل هذه الصفحة. ولمزيد من الأمثلة (المرتكزة على المتصفحات)، يمكنك الاطلاع على هذا ا[http://www.html5rocks.com/en/tutorials/file/filesystem/ لمقال الرائع حول FileSystem] .  


للتعرف على خيارات التخزين الأخرى، يرجى الرجوع إلى [[Cordova/storage|دليل التخزين]].  
للتعرف على خيارات التخزين الأخرى، يرجى الرجوع إلى [[Cordova/storage|دليل التخزين]].  


تعرّف إضافة الملفات كائنًا عامًّا <code>cordova.file</code>. وعلى الرغم من أنّ هذا الكائن موجود في النطاق العام (global scope)، إلا أنه لن يكون متوفرًا إلا بعد إطلاق الحدث <code>[[Cordova/events#deviceready|deviceready]]</code>. <syntaxhighlight lang="javascript">document.addEventListener("deviceready", onDeviceReady, false);
تعرّف إضافة الملفات كائنًا عامًّا هو <code>cordova.file</code> الذي على الرغم من كونه موجودًا في النطاق العام (global scope)، إلا أنه لن يكون متوفرًا إلا بعد إطلاق الحدث <code>[[Cordova/events#deviceready|deviceready]]</code>. <syntaxhighlight lang="javascript">document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
function onDeviceReady() {
     console.log(cordova.file);
     console.log(cordova.file);
سطر 21: سطر 24:


== التثبيت ==
== التثبيت ==
يمكنك تثبيت هذه الإضافة عبر الأمر:<syntaxhighlight lang="javascript">cordova plugin add cordova-plugin-file‎</syntaxhighlight>  
يمكنك تثبيت هذه الإضافة عبر الأمر:<syntaxhighlight lang="shell">cordova plugin add cordova-plugin-file‎</syntaxhighlight>  


== المنصات المدعومة ==  
== المنصات المدعومة ==  
سطر 27: سطر 30:
*iOS  
*iOS  
* OS X  
* OS X  
*ويندوز  
*ويندوز*
*Browser  
*Browser  
لا تدعم هذه المنصات التابعين <code>FileReader.readAsArrayBuffer</code> أو <code>FileWriter.write(blob)</code>‎.
<nowiki>*</nowiki> لا تدعم هذه المنصات التابعين <code>FileReader.readAsArrayBuffer</code> و <code>FileWriter.write(blob)</code>‎.


== مكان تخزين الملفات (Where to Store Files) ==  
== مكان تخزين الملفات ==  


بدءًا من الإصدار 1.2.0، صار استخدام العناوين (URL) لمجلدات نظام الملفات المهمة متاحًا. العناوين تكون على الشكل: <code>file:///path/to/spot/‎</code>، ويمكن تحويلها إلى كائنٍ <code>DirectoryEntry</code> باستخدام التابع <code>window.resolveLocalFileSystemURL()‎</code>.  
بدءًا من الإصدار 1.2.0، صار استخدام العناوين URL للمجلدات المهمة في نظام الملفات متاحًا. تلك العناوين مُصاغة وفق الشكل التالي: <code>file:///path/to/spot/‎</code>، ويمكن تحويلها إلى الكائن <code>DirectoryEntry</code> باستخدام التابع <code>window.resolveLocalFileSystemURL()‎</code>.  
* <code>cordova.file.applicationDirectory</code> - المجلد الذي ثُبِّت فيه التطبيق، وهو للقراءة فقط. (iOS، أندرويد، BlackBerry 10، OSX، ويندوز)  
* <code>cordova.file.applicationDirectory</code> - المجلد الذي ثُبِّت فيه التطبيق، وهو للقراءة فقط. (iOS، أندرويد، BlackBerry 10، OSX، ويندوز)  
* <code>cordova.file.applicationStorageDirectory</code> - المجلد الجذري لصندوق للتطبيق (application's sandbox)؛ على منصتي iOS وويندوز، يكون هذا المجلد للقراءة فقط (لكن بعض المجلدات الفرعية [مثل ‎<code>/Documents</code> في منصة iOS أو ‎<code>/localState</code> في ويندوز] قابلة للقراءة والكتابة معًا). جميع البيانات المضمنة داخل هذا المجلد ستبقى مخصوصة بالتطبيق. (iOS وأندرويد و BlackBerry 10 و OSX)  
* <code>cordova.file.applicationStorageDirectory</code> - المجلد الجذري لبيئة التطبيق التجريبية (application's sandbox)؛ على منصتي iOS وويندوز، يكون هذا المجلد للقراءة فقط (لكن بعض المجلدات الفرعية، مثل ‎<code>/Documents</code> في منصة iOS أو ‎<code>/localState</code> في ويندوز، قابلة للقراءة والكتابة معًا). جميع البيانات المضمنة داخل هذا المجلد ستبقى مخصوصة بالتطبيق. (iOS وأندرويد و BlackBerry 10 و OSX)  
* <code>cordova.file.dataDirectory</code> - مجلد لتخزين البيانات الدائمة والخاصة داخل صندوق التطبيق (application's sandbox) باستخدام الذاكرة الداخلية (على منصة أندرويد، إن كنت بحاجة إلى استخدام ذاكرة خارجية، فاستخدم ‎<code>.externalDataDirectory</code>). على منصة iOS، لا يُزامَن هذا المجلد مع السحابة iCloud (استخدم ‎<code>.syncedDataDirectory</code>). (ويندوز، أندرويد، iOS و BlackBerry 10)  
* <code>cordova.file.dataDirectory</code> - مجلد لتخزين البيانات الدائمة والخاصة داخل بيئة التطبيق التجريبية (application's sandbox) باستخدام الذاكرة الداخلية (على منصة أندرويد، إن كنت بحاجة إلى استخدام ذاكرة خارجية، فاستخدم ‎<code>.externalDataDirector</code>). على منصة iOS، لا يُزامَن هذا المجلد مع السحابة iCloud (استخدم لأجل ذلك ‎<code>.syncedDataDirectory</code>). (ويندوز، أندرويد، iOS و BlackBerry 10)  
* <code>cordova.file.cacheDirectory</code> - مجلد للتخزين المؤقت لملفات البيانات، أو الملفات التي يمكن للتطبيق إعادة إنشائها بسهولة. قد يحذف نظام التشغيل هذه الملفات عندما يشعر بانحسار ذاكرة الجهاز، ولكن يجب ألا تعتمد التطبيقات على نظام التشغيل لحذف الملفات الموجودة في هذا المجلد. (iOS، أندرويد، BlackBerry 10، OSX، ويندوز)  
* <code>cordova.file.cacheDirectory</code> - مجلد للتخزين المؤقت لملفات البيانات، أو الملفات التي يمكن للتطبيق إعادة إنشائها بسهولة. قد يحذف نظام التشغيل هذه الملفات عندما يشعر بانحسار ذاكرة الجهاز، ولكن يجب ألا يعوِّل تطبيقك على نظام التشغيل لحذف الملفات الموجودة في هذا المجلد. (iOS، أندرويد، BlackBerry 10، OSX، ويندوز)  
* <code>cordova.file.externalApplicationStorageDirectory</code> - مساحة التطبيق على وحدة التخزين الخارجية - external storage - (أندرويد)  
* <code>cordova.file.externalApplicationStorageDirectory</code> - مساحة التطبيق على وحدة التخزين الخارجية (external storage). (أندرويد)  
* <code>cordova.file.externalDataDirectory</code> - المجلد الذي ستوضع فيه ملفات البيانات الخاصة بالتطبيق على وحدة التخزين الخارجية. (أندرويد)  
* <code>cordova.file.externalDataDirectory</code> - المجلد الذي ستوضع فيه ملفات البيانات الخاصة بالتطبيق على وحدة التخزين الخارجية. (أندرويد)  
* <code>cordova.file.externalCacheDirectory</code> - ذاكرة التخزين المؤقت للتطبيق في وحدة التخزين الخارجية. (أندرويد)  
* <code>cordova.file.externalCacheDirectory</code> - ذاكرة التخزين المؤقت للتطبيق في وحدة التخزين الخارجية. (أندرويد)  
* <code>cordova.file.externalRootDirectory</code> - المجلد الجذري (root) لوحدة التخزين الخارجية (بطاقة SD). (أندرويد، BlackBerry 10)  
* <code>cordova.file.externalRootDirectory</code> - المجلد الجذري (root) لوحدة التخزين الخارجية (بطاقة SD). (أندرويد، BlackBerry 10)  
* <code>cordova.file.tempDirectory</code> - مجلد يضم الملفات المؤقتة التي يمكن لنظام التشغيل مسحها في أي وقت. لا تعتمد على نظام التشغيل لمحو محتويات هذا المجلد. يجب أن يزيل تطبيقك دائمًا الملفات الموجودة في هذا التطبيق بحسب الاقتضاء. (iOS، OSX، ويندوز)  
* <code>cordova.file.tempDirectory</code> - مجلد يضم الملفات المؤقتة التي يمكن لنظام التشغيل مسحها في أي وقت. لا تعتمد على نظام التشغيل لمحو محتويات هذا المجلد. يجب أن يزيل تطبيقك دائمًا الملفات الموجودة في هذا المجلد بحسب الحاجة. (iOS ،OSX، ويندوز)  
* <code>cordova.file.syncedDataDirectory</code> - يحتوي هذا المجلد ملفات التطبيق التي يجب مزامنتها (مثلًا، مع السحابة iCloud). (ويندوز، iOS)  
* <code>cordova.file.syncedDataDirectory</code> - يحتوي هذا المجلد ملفات التطبيق التي يجب مزامنتها (مثلًا، مع السحابة iCloud). (ويندوز، iOS)  
* <code>cordova.file.documentsDirectory</code> - يضم هذا المجلد الملفات الخاصة بالتطبيق، والتي لها أهمية للتطبيقات الأخرى (مثل ملفات Office). لاحظ أنه في منصة OSX، هذا المجلد هو مجلد المستخدم ‎<code>~/Documents</code>. ‏(iOS، OSX)  
* <code>cordova.file.documentsDirectory</code> - يضم هذا المجلد الملفات الخاصة بالتطبيق، والتي لها أهمية للتطبيقات الأخرى (مثل ملفات Office). لاحظ أنه في منصة OSX، هذا المجلد هو مجلد المستخدم ‎<code>~/Documents</code>. ‏(iOS، OSX)  
* <code>cordova.file.sharedDirectory</code> - يحتوي هذا المجلد على الملفات المتاحة لجميع التطبيقات (BlackBerry 10)
* <code>cordova.file.sharedDirectory</code> - يحتوي هذا المجلد على الملفات المتاحة لجميع التطبيقات. (BlackBerry 10)
== بنيات نظام الملفات (File System Layouts) ==  
== تخطيط نظام الملفات (File System Layouts) ==  


على الرغم من أن بنيات نظام الملفات من الناحية الفنية تُعد من تفاصيل التقديم (implementation)، إلا أنه قد يكون من المفيد معرفة كيفية الربط بين الخاصيات <code>cordova.file.*‎</code> وبين المسارات الفعلية على الجهاز الحقيقي.  
على الرغم من أن تخطيط نظام الملفات من الناحية الفنية تُعد من تفاصيل التقديم (implementation)، إلا أنه قد يكون من المفيد معرفة كيفية الربط بين الخاصيات <code>cordova.file.*‎</code> وبين المسارات الفعلية على الجهاز الحقيقي.  
=== بنية نظام الملفات في منصة iOS ===
=== بنية نظام الملفات في منصة iOS ===
{| class="wikitable"
{| class="wikitable"
!مسار الجهاز
!مسار الجهاز
!<code>cordova.file.*</code>
!<code>cordova.file.*</code>
!<code>iosExtraFileSystems</code>
!<code>iosExtraFileSystems</code>
!كتابة/قراءة؟
!كتابة/قراءة؟
سطر 60: سطر 63:
!خاص
!خاص
|-
|-
|<code>‎/var/mobile/Applications/<UUID>/‎</code>
|<code>‎/var/mobile</code><code>
/Applications/<UUID>/‎</code>
|<code>applicationStorageDirectory</code>
|<code>applicationStorageDirectory</code>
|<code>-</code>
|<code>-</code>
سطر 154: سطر 158:
* <code>*</code> => ملفات تستمر في الذاكرة حتى بعد إعادة تشغيل التطبيق وترقيته، ولكن يمكن أن يمحو نظام التشغيل هذا المجلد في أي وقت. يجب أن يكون تطبيقك قادرًا على إعادة إنشاء أي محتوى مهدد بالحذف.
* <code>*</code> => ملفات تستمر في الذاكرة حتى بعد إعادة تشغيل التطبيق وترقيته، ولكن يمكن أن يمحو نظام التشغيل هذا المجلد في أي وقت. يجب أن يكون تطبيقك قادرًا على إعادة إنشاء أي محتوى مهدد بالحذف.


* <code>**</code> => قد تستمر هذه الملفات عبر إعادة تشغيل التطبيق، ولكنّ ذلك ليس أكيدًا. لا يمكن ضمان استمرار هذه الملفات عبر التحديثات. يجب أن يزيل تطبيقك الملفات من هذا المجلد بنفسه، لأنّه لا توجد ضمانة على أنّ نظام التشغيل سيمحوا (أو متى يفعل ذلك) هذه الملفات.
* <code>**</code> => قد تستمر هذه الملفات عبر إعادة تشغيل التطبيق، ولكنّ ذلك ليس أكيدًا. لا يمكن ضمان استمرار هذه الملفات بعد إجراء التحديثات. يجب أن يزيل تطبيقك الملفات من هذا المجلد بنفسه، لأنّه لا توجد ضمانة على أنّ نظام التشغيل سيمحوا هذه الملفات (أو متى يفعل ذلك).


* <code>***</code> => قد يمحو نظام التشغيل محتويات هذا المجلد متى رأى أنّ ذلك ضروري، ولكن لا تعتمد على هذا السلوك. يجب عليك مسح هذا المجلد بما يتناسب مع تطبيقك.
* <code>***</code> => قد يمحو نظام التشغيل محتويات هذا المجلد متى رأى أنّ ذلك ضروري، ولكن لا تعتمد على هذا السلوك. يجب عليك مسح هذا المجلد بما يتناسب مع تطبيقك.
سطر 161: سطر 165:
{| class="wikitable"
{| class="wikitable"
!مسار الجهاز
!مسار الجهاز
!<code>cordova.file.*</code>
!<code>cordova.file.*</code>
!<code>AndroidExtraFileSystems</code>
!<code>AndroidExtraFileSystems</code>
!كتابة/قراءة؟
!قراءة/كتابة؟
!مستمرة؟
!مستمرة؟
!أيمحوه نظام التشغيل؟
!أيمحوه نظام التشغيل؟
سطر 244: سطر 248:
* <code>*</code> => قد يمحو نظام التشغيل هذا المجلد بشكل دوري، ولكن لا تعتمد على هذا السلوك. امسح محتويات هذا المجلد بالشكل المناسب لتطبيقك. في حالة قيام المستخدم بمسح ذاكرة التخزين المؤقت يدويًا، ستزال محتويات هذا المجلد.
* <code>*</code> => قد يمحو نظام التشغيل هذا المجلد بشكل دوري، ولكن لا تعتمد على هذا السلوك. امسح محتويات هذا المجلد بالشكل المناسب لتطبيقك. في حالة قيام المستخدم بمسح ذاكرة التخزين المؤقت يدويًا، ستزال محتويات هذا المجلد.


* <code>**</code> => قلا يمحو نظام التشغيل هذا المجلد تلقائيًا؛ فأنت المسؤول عن إدارة محتويات المجلد بنفسك. عندما يمحو المستخدم ذاكرة التخزين المؤقت يدويا، ستزال محتويات هذا المجلد.
* <code>**</code> => لا يمحو نظام التشغيل هذا المجلد تلقائيًا؛ فأنت المسؤول عن إدارة محتوياته بنفسك. عندما يمحو المستخدم ذاكرة التخزين المؤقت يدويا، ستزال محتويات هذا المجلد.


'''ملاحظة''': إذا تعذر تركيب وحدة التخزين الخارجية، ستساوي الخاصيات <code>cordova.file.external*‎</code> القيمة <code>null</code>.  
'''ملاحظة''': إذا تعذر وصل وحدة التخزين الخارجية، ستساوي الخاصيات <code>cordova.file.external*‎</code> القيمة <code>null</code>.  
=== بنية نظام ملفات منصة OS X ===
=== بنية نظام ملفات منصة OS X ===
{| class="wikitable"
{| class="wikitable"
!مسار الجهاز
!مسار الجهاز
!<code>cordova.file.*</code>
!<code>cordova.file.*</code>
!<code>iosExtraFileSystems</code>
!<code>iosExtraFileSystems</code>
!كتابة/قراءة؟
!قراءة/كتابة؟
!أيمحوه نظام التشغيل؟
!أيمحوه نظام التشغيل؟
!خاص
!خاص
سطر 311: سطر 315:
|لا**
|لا**
|لا
|لا
|}'''ملاحظة''': هذه هي البنية الخاصة بالتطبيقات غير المحصنة (non sandboxed applications). إذا قمت بتحصين (sandboxing) التطبيق، فسيصبح الملف<code>applicationStorageDirectory</code> داخل المجلد ‎<code>~/Library/Containers/<bundle-id>/Data/Library/Application Support</code>.  
|}'''ملاحظة''': هذه هي البنية الخاصة بالتطبيقات غير التجريبية (non sandboxed applications). إذا قمت باستعمال البيئة التجريبية (sandboxing) للتطبيق، فسيصبح الملف <code>applicationStorageDirectory</code> داخل المجلد ‎<code>~/Library/Containers/<bundle-id>/Data/Library/Application Support</code>.  


* <code>*</code> = > ملفات تستمر بعد إعادة تشغيل التطبيق أو ترقيته، ولكن يمكن أن يمحو نظام التشغيل هذا المجلد في أي وقت. يجب أن يكون تطبيقك قادرًا على إعادة إنشاء أي محتوى قد يتم حذفه. يجب عليك مسح هذا المجلد بنفسك بما يلائم تطبيقك.  
* <code>*</code> => ملفات تستمر بعد إعادة تشغيل التطبيق أو ترقيته، ولكن يمكن أن يمحو نظام التشغيل هذا المجلد في أي وقت. يجب أن يكون تطبيقك قادرًا على إعادة إنشاء أي محتوى قد يتم حذفه. يجب عليك مسح هذا المجلد بنفسك بما يلائم تطبيقك.  


* <code>**</code> => يتيح الوصول إلى نظام الملفات بأكمله. وهذا غير متوفر إلا للتطبيقات غير المحصنة.  
* <code>**</code> => يتيح الوصول إلى نظام الملفات بأكمله. وهذا غير متوفر إلا للتطبيقات غير المحصنة.  
سطر 319: سطر 323:
{| class="wikitable"
{| class="wikitable"
!مسار الجهاز
!مسار الجهاز
!<code>cordova.file.*</code>
!<code>cordova.file.*</code>
!كتابة/قراءة؟
!قراءة/كتابة؟
!أمستمر؟
!أمستمر؟
!أيمحوه نظام التشغيل؟
!أيمحوه نظام التشغيل؟
سطر 361: سطر 365:
|}  
|}  


* <code>*</code> => قد يمحو نظام التشغيل هذا المجلد دوريًا  
* <code>*</code> => قد يمحو نظام التشغيل هذا المجلد دوريًا.


==ملاحظات خاصة بمنصة أندرويد ==  
==ملاحظات خاصة بمنصة أندرويد ==  
=== موضع التخزين الدائم في أندرويد ===  
=== موضع التخزين الدائم في أندرويد (Android Persistent storage location) ===  


هناك عدة مواضع صالحة لتخزين الملفات بشكل دائم على أجهزة أندرويد . راجع [http://developer.android.com/guide/topics/data/data-storage.html هذه الصفحة] لمعلومات مفصلة بخصوص مختلف إمكانيات التخزين المتاحة.  
هناك عدة مواضع صالحة لتخزين الملفات بشكل دائم على أجهزة أندرويد . راجع [http://developer.android.com/guide/topics/data/data-storage.html هذه الصفحة] لمعلومات مفصلة بخصوص مختلف إمكانيات التخزين المتاحة.  


كانت الإصدارات السابقة من هذه الإضافة تختار موضع الملفات المؤقتة والمستمرة (persistent) عند بدء التشغيل، بحسب ما إذا تم تركيب بطاقة الذاكرة SD (أو أي أداة تخزين مكافئة) على الجهاز أم لا. إن رُكِّبت بطاقة الذاكرة SD، أو إن توفرت مساحة تخزين داخلية (على أجهزة Nexus مثلاً)، فستُخزّن الملفات المستقرة في المجلد الجذري لتلك المساحة. هذا يعني أن جميع تطبيقات كورودوفا ستكون قادرة على رؤية جميع الملفات المتوفرة على البطاقة.  
كانت الإصدارات السابقة من هذه الإضافة تختار موضع الملفات المؤقتة والمستمرة (persistent) عند بدء التشغيل، بحسب ما إذا تم وصل (mounted) بطاقة الذاكرة SD (أو أي أداة تخزين مكافئة) على الجهاز أم لا. إن وُصلَت البطاقة SD، أو إن توفرت مساحة تخزين داخلية (على أجهزة Nexus مثلاً)، فستُخزّن الملفات المستمرة في المجلد الجذري لتلك المساحة. هذا يعني أن جميع تطبيقات كورودوفا ستكون قادرة على رؤية جميع الملفات المتوفرة على البطاقة.  


في الإصدارات السابقة، إذا لم تكن بطاقة الذاكرة SD متوفرة، فستُخزّن البيانات ضمن المجلد ‎<code>/data/data/<packageId>‎</code>، والذي يعزل التطبيقات عن بعضها البعض، ولكن قد يسمح بتشارك البيانات بين المستخدمين.  
في الإصدارات السابقة، إذا لم تكن بطاقة الذاكرة SD متوفرة، فستُخزّن البيانات ضمن المجلد ‎<code>/data/data/<packageId>‎</code>، والذي يعزل التطبيقات عن بعضها البعض، ولكن قد يسمح بتشارك البيانات بين المستخدمين.  


من الممكن الآن الاختيار بين تخزين الملفات في وحدة التخزين الداخلية (internal storage)، أو استخدام المقاربة السابقة، يمكنك فعل هذا عبر الوسم <code>preference</code> في الملف <code>[[Cordova/config ref|config.xml]]</code>. عبر إضافة أحد هذين السطرين إليه:  
من الممكن الآن الاختيار بين تخزين الملفات في وحدة التخزين الداخلية (internal storage)، أو استخدام المقاربة السابقة، يمكنك فعل هذا عبر الوسم <code>[[Cordova/config ref#preference|preference]]</code> في الملف <code>[[Cordova/config ref|config.xml]]</code>. عبر إضافة أحد هذين السطرين إليه:  
<syntaxhighlight lang="xml"><preference name="AndroidPersistentFileLocation" value="Internal" />
<syntaxhighlight lang="xml"><preference name="AndroidPersistentFileLocation" value="Internal" />
<preference name="AndroidPersistentFileLocation" value="Compatibility" />‎</syntaxhighlight>  
<preference name="AndroidPersistentFileLocation" value="Compatibility" />‎</syntaxhighlight>  


بدون هذا السطر، ستستخدم إضافة الملفات القيمة <code>Internal</code> كإعداد افتراضي. وفي حال كان الوسم <code>preference</code> حاضرًا، ولم تكن له إحدى هذه القيم، فلن يعمل التطبيق.  
بدون هذا السطر، ستستخدم إضافة الملفات القيمة <code>Internal</code> كإعداد افتراضي. وفي حال كان الوسم <code>[[Cordova/config ref#preference|preference]]</code> حاضرًا، ولم يٌعطى إحدى هاتين القيمتين، فلن يعمل التطبيق.  
 
إذا سبق وأرسلت تطبيقك إلى المستخدمين باستخدام إصدار قديم (قبل الإصدار 3.0.0) من هذه الإضافة، وكان التطبيق قد خزّن الملفات في نظام الملفات الدائمة (persistent filesystem)، فيجب إعطاء الوسم <code>[[Cordova/config ref#preference|preference]]</code> القيمة <code>Compatibility</code> إذا لم يحدد الملف <code>[[Cordova/config ref|config.xml]]</code> موضع نظام الملفات الدائمة. 


إذا سبق وأرسلت تطبيقك إلى المستخدمين باستخدام إصدار قديم (قبل الإصدار 3.0.0) من هذه الإضافة، وكان التطبيق قد خزّن الملفات في نظام الملفات الدائمة (persistent filesystem)، فيجب إعطاء الوسم <code>preference</code> القيمة <code>Compatibility</code> إذا لم يحدد الملف <code>[[Cordova/config ref|config.xml]]</code> موضع نظام الملفات الدائمة. قد يؤدي تبديل موضع التخزين وجعله "داخليا" (<code>Internal</code>) إلى عدم استطاعة المستخدمين الحاليين الذين يقومون بترقية تطبيقاتهم من الوصول إلى ملفاتهم المخزنة مسبقًا، وذلك اعتمادًا على الجهاز المستخدم.  
قد يؤدي تبديل موضع التخزين وجعله "داخليًّا" (<code>Internal</code>) إلى عدم استطاعة المستخدمين الحاليين الذين يقومون بترقية تطبيقاتهم الوصولَ إلى ملفاتهم المخزنة مسبقًا، وذلك اعتمادًا على الجهاز المستخدم.  


إذا كان تطبيقك جديدًا، أو لم يسبق له تخزين الملفات في نظام الملفات الدائمة، فيفضل عمومًا استخدام الإعداد <code>Internal</code>.  
إذا كان تطبيقك جديدًا، أو لم يسبق له تخزين الملفات في نظام الملفات الدائمة، فيفضل عمومًا استخدام الإعداد <code>Internal</code>.  
=== العمليات العودية البطيئة على المجلد <code>‎/android_asset</code> ===  
=== العمليات العودية البطيئة على المجلد <code>‎/android_asset</code> ===  


العمل على مجلدات الأصول (asset directories) بطيئة جدا في أندرويد. يمكنك تسريع ذلك عن طريق إضافة <code>src/android/build-extras.gradle</code> إلى جذر مشروع أندرويد (يتطلب الإصدار cordova-android@4.0.0 أو ما بعده).  
العمل على مجلدات الأصول (asset directories) بطيئ جدًا في أندرويد. يمكنك تسريع ذلك عن طريق إضافة <code>src/android/build-extras.gradle</code> إلى جذر مشروع أندرويد (يتطلب الإصدار cordova-android@4.0.0 أو ما بعده).  
=== الإذن في الكتابة في وحدة التخزين الخارجية عندما لا تكون مُركّبة في منصة Marshmallow ===  
=== إذن الكتابة على وحدة تخزين خارجية غير موصولة في الإصدار Marshmallow ===  


تتطلب منصة Marshmallow أن تستأذن التطبيقات قبل القراءة أو الكتابة في المواضع الخارجية. [http://developer.android.com/guide/topics/data/data-storage.html#filesExternal افتراضيًا]، يملك تطبيقك الإذن في الكتابة في <code>cordova.file.applicationStorageDirectory</code> و <code>cordova.file.externalApplicationStorageDirectory</code>، ولن يكون على الإضافة طلب إذن للكتابة في هذين المجلدين إلا إذا لم تُركّب وحدة تخزين خارجية. وفي هذه الحالة، فستطلب الإضافة الإذن للكتابة في <code>cordova.file.externalApplicationStorageDirectory</code>.  
يتطلب الإصدار Marshmallow أن تستأذن التطبيقات قبل القراءة أو الكتابة في المواضع الخارجية. [http://developer.android.com/guide/topics/data/data-storage.html#filesExternal افتراضيًا]، يملك تطبيقك الإذن في الكتابة في <code>cordova.file.applicationStorageDirectory</code> و <code>cordova.file.externalApplicationStorageDirectory</code>، ولن يكون على الإضافة الاستئذان للكتابة في هذين المجلدين إلا إذا لم توصل (mounte) وحدة تخزين خارجية. وفي هذه الحالة، فستطلب الإضافة الإذن للكتابة في <code>cordova.file.externalApplicationStorageDirectory</code>.  


== ملاحظات خاصة بمنصة IOS ==  
== ملاحظات خاصة بمنصة iOS ==  
* <code>cordova.file.applicationStorageDirectory</code> للقراءة فقط؛ ستفشل أي محاولة لتخزين الملفات داخل المجلد الجذري. استخدم أحد الخاصيات <code>cordova.file.*</code> الأخرى المحددة لأجل منصة iOS (وحدهما المجلدان <code>applicationDirectory</code> و <code>applicationStorageDirectory</code> للقراءة فقط).  
* <code>cordova.file.applicationStorageDirectory</code> للقراءة فقط؛ ستفشل أي محاولة لتخزين الملفات داخل المجلد الجذري. استخدم أحد الخاصيات <code>cordova.file.*</code> الأخرى المحددة لأجل منصة iOS (فقط المجلدان <code>applicationDirectory</code> و <code>applicationStorageDirectory</code> للقراءة فقط).  
*<code>FileReader.readAsText(blob, encoding)</code>  
*<code>FileReader.readAsText(blob, encoding)</code>
* المعامل <code>encoding</code> غير مدعوم، والترميز UTF-8 هو المعتمد دائمًا.
** المعامل <code>encoding</code> غير مدعوم، والترميز UTF-8 هو المعتمد دائمًا.


=== موضع التخزين الدائم في منصة iOS ===  
=== موضع التخزين الدائم في منصة iOS ===  


هناك موضعان يصلحان لتخزين الملفات الدائمة على جهاز iOS: مجلد المستندات (Documents directory) ومجلد المكتبة (Library directory). الإصدارات السابقة من الإضافة كانت تخزّن الملفات الدائمة خصرًا في مجلد المستندات. وهذا جعل جميع ملفات التطبيق مرئية في تطبيق iTunes، وهو ما لم يكن مقصودًا غالبًا، خاصة للتطبيقات التي تتعامل مع الكثير من الملفات الصغيرة، بدلاً من إنتاج مستندات كاملة لتصديرها، وهو الغرض المقصود من المجلد.  
هناك موضعان يصلحان لتخزين الملفات الدائمة على جهاز iOS: مجلد المستندات (Documents directory) ومجلد المكتبة (Library directory). الإصدارات السابقة من الإضافة كانت تخزّن الملفات الدائمة حصرًا في مجلد المستندات. وهذا جعل جميع ملفات التطبيق مرئية في تطبيق iTunes، وهو أمرٌ لم يكن مرغوبًا غالبًا، خاصة للتطبيقات التي تتعامل مع الكثير من الملفات الصغيرة، بدلًا من إنتاج مستندات كاملة لتصديرها، وهو الغرض المقصود من المجلد.  


من الممكن الآن اختيار تخزين الملفات في مجلد المستندات أو مجلد المكتبة، عبر الوسم preference في الملف <code>config.xml</code> الخاص بتطبيقك. عبر إضافة أحد هذين السطرين إلى <code>config.xml</code>:  
من الممكن الآن اختيار تخزين الملفات في مجلد المستندات أو مجلد المكتبة، عبر الوسم [[Cordova/config ref#preference|<code>preference</code>]] في الملف <code>[[Cordova/config ref|config.xml]]</code>. وذلك عبر إضافة أحد هذين السطرين إلى <code>[[Cordova/config ref|config.xml]]</code>:  
<syntaxhighlight lang="javascript"><preference name="iosPersistentFileLocation" value="Library" />
<syntaxhighlight lang="xml"><preference name="iosPersistentFileLocation" value="Library" />
<preference name="iosPersistentFileLocation" value="Compatibility" />‎</syntaxhighlight>  
<preference name="iosPersistentFileLocation" value="Compatibility" />‎</syntaxhighlight>  


بدون هذا السطر، ستستخدم الإضافة <code>Compatibility</code> كإعداد افتراضي. في حال كان الوسم preference حاضرًا، ولم يكن يساوي إحدى هذه القيم، فلن يعمل التطبيق.  
بدون هذا السطر، ستستخدم الإضافةُ القيمةَ <code>Compatibility</code> كإعداد افتراضي. في حال كان الوسم <code>[[Cordova/config ref#preference|preference]]</code> حاضرًا، ولم يُعطى إحدى هاتين القيمتين، فلن يعمل التطبيق.  


إن سبق وأرسلت تطبيقك إلى المستخدمين، باستخدام إصدار قديم (قبل الإصدار 1.0) من هذه الإضافة، وكان قد خزّن الملفات في نظام الملفات الدائمة، فعليك تعيين الوسم preference عند القيمة <code>Compatibility</code>. تحويل الموضع إلى <code>Library</code> يعني أن المستخدمين الحاليين الذين يقومون بترقية تطبيقاتهم لن يتمكنوا من الوصول إلى ملفاتهم المخزنة مسبقًا.  
إن سبق وأرسلت تطبيقك إلى المستخدمين باستخدام إصدار قديم (قبل الإصدار 1.0) من هذه الإضافة، وكنت قد خزّنت الملفات في نظام الملفات الدائمة، فعليك إعطاء الوسم <code>[[Cordova/config ref#preference|preference]]</code> القيمة <code>Compatibility</code>. تحويل الموضع إلى المكتبة (<code>Library</code>) يعني أن المستخدمين الحاليين الذين يقومون بترقية تطبيقاتهم لن يتمكنوا من الوصول إلى ملفاتهم المخزنة مسبقًا.  


إن كان تطبيقك جديدًا، أو لم يسبق له تخزين الملفات في نظام الملفات الدائمة، فيفضل عمومًا استخدام الإعداد <code>Library</code>.  
إن كان تطبيقك جديدًا، أو لم يسبق له تخزين الملفات في نظام الملفات الدائمة، فيفضل عمومًا استخدام الإعداد <code>Library</code>.  
سطر 409: سطر 415:
== ملاحظات خاصة بالمتصفحات (Browsers) ==  
== ملاحظات خاصة بالمتصفحات (Browsers) ==  
=== ملاحظات خاصة وتوضيحات ===  
=== ملاحظات خاصة وتوضيحات ===  
* يستخدم كل متصفح نظام ملفات محصّن (sandboxed) خاص به. يستخدم المتصفحان IE و فايرفوكس نظام الملفات IndexedDB كأساس. وتستخدم جميع المتصفحات عارضة مائلة للأمام كفاصلة داخل المسار.  
* يستخدم كل متصفح نظام ملفات محصّن (sandboxed) خاص به. يستخدم المتصفحان IE و فايرفوكس الواجهة البرمجية [[Cordova/storage#.D8.A7.D9.84.D9.88.D8.A7.D8.AC.D9.87.D8.A9 IndexedDB|IndexedDB]]. كما تستخدم جميع المتصفحات خط مائل ("<code>/</code>") كفاصلة داخل المسار.  
* يجب إنشاء مدخلات المجلد على التوالي. على سبيل المثال، سيفشل استدعاء التابع <code>fs.root.getDirectory('dir1/dir2', {create:true}, successCallback, errorCallback)</code> إذا لم يكن المجلد dir1 موجودًا.  
* يجب إنشاء مدخلات المجلد بالتتابع. على سبيل المثال، سيفشل استدعاء التابع <code>fs.root.getDirectory('dir1/dir2', {create:true}, successCallback, errorCallback)</code> إذا لم يكن المجلد <code>dir1</code> موجودًا.  
* تستأذن الإضافة من المستخدم لاستخدام التخزين الدائم عند بدء التطبيق لأول مرة.  
* تستأذن الإضافة من المستخدم لاستخدام التخزين الدائم عند بدء التطبيق لأول مرة.  
* تدعم الإضافة <code>cdvfile://localhost</code> (الموارد المحلية) فقط. أي أنّ <code>cdvfile</code> لا يدعم الموارد الخارجية.  
* تدعم الإضافة <code>cdvfile://localhost</code> (الموارد المحلية) فقط. أي أنّ البروتوكول <code>cdvfile</code> لا يدعم الموارد الخارجية.  
* لا تتقيّد الإضافة [http://www.w3.org/TR/2011/WD-file-system-api-20110419/#naming-restrictions "File System API 8.3 Naming restrictions"].  
* لا تتقيّد الإضافة [http://www.w3.org/TR/2011/WD-file-system-api-20110419/#naming-restrictions "بتسميات الواجهة البرمجية لنظام الملفات 8.3"].  
* الكائن Blob و تابع الصنف File ‏ <code>close</code> غير مدعومان.  
* الكائن Blob و التابع‏ <code>close</code> غير مدعومان.  
* لا تدعم هذه الإضافة <code>FileSaver</code> و <code>BlobBuilder</code> وليس لهما أكواد مُجتزأة (stubs).  
* لا تدعم هذه الإضافة <code>FileSaver</code> و <code>BlobBuilder</code>، وليس لهما جذوع (stubs).  
* لا تدعم الإضافة <code>requestAllFileSystems</code>. هذه الدالة غير موجودة في المواصفات أيضًا.  
* الإضافة لا تدعم الدالة <code>requestAllFileSystems</code>. هذه الدالة غير موجودة في المواصفات أيضًا.  
* لن تتم إزالة المُدخلات في المجلد إن كنت تستخدم الراية <code>create: true</code> مع مجلد موجود.  
* لن تُزال المُدخلات (Entries) من المجلد إن كنت تستخدم الراية <code>create: true</code> مع مجلد موجود.  
* الملفات المُنشأة عبر الباني (constructor) ليست مدعومة. عليك استخدام التابع entry.file بدلاً من ذلك.  
* الملفات المُنشأة عبر الباني (constructor) ليست مدعومة. عليك استخدام التابع <code>entry.file</code> بدلًا من ذلك.  
* يستخدم كل متصفح شكلًا خاصًا من عناوين blob المرجعية.  
* يستخدم كل متصفح شكلًا خاصًا من عناوين blob.  
* الدالة <code>readAsDataURL</code> مدعومة، لكن نوع الوسيط (mediatype) في متصفح كروم يعتمد على امتداد اسم المُدخلات (entry name extension)، نوع الوسيط mediatype في المتصفح IE دائمًا فارغ (وهو أمر مماثل لـ <code>text-plain</code> وفقًا للمواصفات)، أما في متصفح فايرفوكس فإنّ mediatype تساوي دائمًا <code>application/octet-stream</code>. على سبيل المثال، إن كان المحتوى هو <code>abcdefg</code>، فحينئذٍ سيعيد المتصفح فايرفوكس القيمة <code>data:application/octet-stream;base64,YWJjZGVmZw==</code>، وسيعيد المتصفح IE القيمة <code>data:;base64,YWJjZGVmZw==</code>، فيما سيعيد المتصفح كروم القيمة <code>data:<mediatype depending on extension of entry name>;base64,YWJjZGVmZw==</code>.  
* الدالة <code>readAsDataURL</code> مدعومة، لكنّ نوع الوسيط <code>mediatype</code> في متصفح كروم يعتمد على امتداد اسم المُدخلات (entry name extension)؛ نوع الوسيط <code>mediatype</code> في المتصفح IE يكون دائمًا فارغًا (وهو أمر مماثل لـ <code>text-plain</code> وفقًا للمواصفات)، أما في متصفح فايرفوكس، فإنّ نوع الوسيط <code>mediatype</code> يساوي دائمًا <code>application/octet-stream</code>. على سبيل المثال، إن كان المحتوى هو <code>abcdefg</code>، فحينئذٍ سيعيد فايرفوكس القيمة <code>data:application/octet-stream;base64,YWJjZGVmZw==</code>، وسيعيد المتصفح IE القيمة <code>data:;base64,YWJjZGVmZw==</code>، فيما سيعيد المتصفح كروم القيمة <code>data:<mediatype depending on extension of entry name>;base64,YWJjZGVmZw==</code>.  
* تُعيد الخاصية <code>toInternalURL</code> المسار وفق الصيغة <code>file:///persistent/path/to/entry</code> (على فايرفوكس و IE). فيما يعيد كروم المسار وفق الصيغة <code>cdvfile://localhost/persistent/file</code>.  
* تُعيد الخاصية <code>toInternalURL</code> المسار وفق الصيغة <code>file:///persistent/path/to/entry</code> (على فايرفوكس و IE). فيما يعيد كروم المسار وفق الصيغة <code>cdvfile://localhost/persistent/file</code>.  
=== ملاحظات خاصة بمتصفح كروم ===  
=== ملاحظات خاصة بمتصفح كروم ===  
* نظام الملفات في متصفح كروم لا يكون جاهزًا فور إطلاق الحدث حدث ready الخاص بالجهاز. كحل بديل، يمكنك الاشتراك في الحدث <code>filePluginIsReady</code>. مثال: <code>javascript
* نظام الملفات في متصفح كروم لا يكون جاهزًا أثناء إطلاق الحدث [[Cordova/events#deviceready|<code>deviceready</code>]]؛ لتجاوز هذه المشكلة، يمكنك الاشتراك في الحدث <code>filePluginIsReady</code>. على سبيل مثال:  
window.addEventListener('filePluginIsReady', function(){ console.log('File plugin is ready');}, false);</code> يمكنك استخدام الدالة <code>window.isFilePluginReadyRaised</code> للتحقق مما إن كان الحدث قد أُطلِق بالفعل.  
<syntaxhighlight lang="javascript">
* حصة نظام الملفات window.requestFileSystem المؤقت (TEMPORARY) والدائم (PERSISTENT) غير محدودة في كروم.  
window.addEventListener('filePluginIsReady', function(){ console.log('File plugin is ready');}, false);
* لزيادة سعة التخزين الدائم في كروم، يلزمك استدعاء التابع <code>window.initPersistentFileSystem</code>. تبلغ حصة التخزين الدائم 5 ميغابايت بشكل افتراضي.  
</syntaxhighlight>يمكنك استخدام الدالة <code>window.isFilePluginReadyRaised</code> للتحقق مما إذا كان الحدث قد أُطلِق بالفعل.  
* يتطلب كروم تمرير الوسيط <code>--allow-file-access-from-files</code> إلى الأمر run لدعم الواجهة البرمجية (API) عبر البروتوكول <code>file:///</code>.  
* حصة نظام الملفات <code>window.requestFileSystem</code> المؤقت (TEMPORARY) أو الدائم (PERSISTENT) غير محدودة في متصفح كروم.  
* لزيادة سعة التخزين الدائم (persistent storage) في كروم، يلزمك استدعاء التابع <code>window.initPersistentFileSystem</code>. افتراضيًا، تبلغ حصة التخزين الدائم 5 ميغابايت.  
* يتطلب كروم تمرير الوسيط <code>--allow-file-access-from-files</code> إلى الأمر <code>run</code> لدعم الواجهة البرمجية (API) عبر البروتوكول <code>file:///</code>.  
* لن يُغيّر الكائن <code>File</code> إن كنت تستخدم الراية <code>{create:true}</code> عند الحصول على مدخل <code>Entry</code> موجود.  
* لن يُغيّر الكائن <code>File</code> إن كنت تستخدم الراية <code>{create:true}</code> عند الحصول على مدخل <code>Entry</code> موجود.  
* تُضبط خاصية الأحداث <code>cancelable</code> عند القيمة true في متصفح كروم. على خلاف [http://dev.w3.org/2009/dap/file-system/file-writer.html specification].  
* تُضبط خاصية الأحداث <code>cancelable</code> عند القيمة <code>true</code> في متصفح كروم. على خلاف ما تقوله [http://dev.w3.org/2009/dap/file-system/file-writer.html المواصفات].  
* تعيد الدالة <code>toURL</code> في كروم مسارًا مسبوقا بالبادئة <code>filesystem:</code> بناءً على التطبيق المُضيف. على سبيل المثال، <code>filesystem:file:///persistent/somefile.txt</code>، <code>filesystem:http://localhost:8080/persistent/somefile.txt</code>.  
* تعيد الدالة <code>toURL</code> في كروم مسارًا مسبوقًا بالبادئة <code>filesystem:</code> بناءً على التطبيق المُضيف. مثلًا:
* لا تحتوي نتيجة الدالة <code>toURL</code> على شرطة مائلة في حالة إدخال المجلد. مع ذلك، يحُل كروم المجلدات ذات العناوين (url) التي تنتهي بشرطة مائلة بشكلٍ صحيح.  
** <code>filesystem:file:///persistent/somefile.txt</code>  
* يتطلب التابع <code>resolveLocalFileSystemURL</code> أن يكون للعنوان الخلفي <code>url</code> بادئة <code>filesystem</code>. على سبيل المثال، يجب أن يكون المعامل <code>url</code> الخاص بالتابع <code>resolveLocalFileSystemURL</code> وفق الصيغة <code>filesystem:file:///persistent/somefile.txt</code> بدلاً من الصيغة <code>file:///persistent/somefile.txt</code> المعمول بها في أندرويد.  
** <code>filesystem:<nowiki>http://localhost:8080/persistent/somefile.txt</nowiki></code>.  
* الدالة <code>toNativeURL</code> ليست مدعومة، وليس لديها كعب (stub).  
* لا تحتوي نتيجة الدالة <code>toURL</code> على خط مائل في حالة <code>directoryEntry</code>. مع ذلك، يستبين كروم المجلدات ذات العناوين url التي تنتهي بخط مائل بشكلٍ صحيح.  
* يتطلب التابع <code>resolveLocalFileSystemURL</code> أن يبدأ العنوان الخلفي بالبادئة <code>filesystem</code>. على سبيل المثال، يجب أن يكون المعامل <code>url</code> الخاص بالتابع <code>resolveLocalFileSystemURL</code> مكتوبًا وفق الصيغة <code>filesystem:file:///persistent/somefile.txt</code> بدلًا من الصيغة <code>file:///persistent/somefile.txt</code> المعمول بها في أندرويد.  
* الدالة <code>toNativeURL</code> ليست مدعومة، وليس لها جذع (stub).  
* الدالة <code>setMetadata</code> ليست مذكورة في المواصفات وليست مدعومة.  
* الدالة <code>setMetadata</code> ليست مذكورة في المواصفات وليست مدعومة.  
* يُطلق الخطأ INVALIDMODIFICATIONERR (الكود: 9) بدلاً من الخطأ SYNTAX_ERR (الكود: 8) عند طلب (requesting) نظام ملفات غير موجود.  
* يُطلق الخطأ <code>INVALIDMODIFICATIONERR</code> (ذو الرمز 9) بدلًا من الخطأ <code>SYNTAX_ERR</code> (ذي الرمز 8) عند طلب (requesting) نظام ملفات غير موجود.  
* يُطلق الخطأ INVALIDMODIFICATIONERR (الكود: 9) بدلاً من الخطأ PATHEXISTSERR (الكود: 12) عند محاولة إنشاء ملف أو مجلد، موجود مسبقاً.  
* يُطلق الخطأ <code>INVALIDMODIFICATIONERR</code> (ذو الرمز 9) بدلًا من الخطأ <code>PATHEXISTSERR</code> (ذي الرمز 12) عند محاولة إنشاء ملف أو مجلد موجود مسبقًا.  
* يُطلق الخطأ INVALIDMODIFICATIONERR (الكود: 9) بدلاً من الخطأ NOMODIFICATIONALLOWED_ERR (الكود: 6) عند محاولة استدعاء removeRecursively على المجلد الجذري (root) نظام الملفات.  
* يُطلق الخطأ <code>INVALIDMODIFICATIONERR</code> (ذو الرمز 9) بدلًا من الخطأ <code>NOMODIFICATIONALLOWED_ERR</code> (ذي الرمز 6) عند محاولة استدعاء <code>removeRecursively</code> على المجلد الجذري (root) لنظام الملفات.  
* يُطلق الخطأ INVALIDMODIFICATIONERR (الكود: 9) بدلاً من الخطأ NOTFOUNDERR (الكود: 1) عند محاولة الانتقال إلى مجلد غير موجود.  
* يُطلق الخطأ <code>INVALIDMODIFICATIONERR</code> (ذو الرمز 9) بدلًا من الخطأ <code>NOTFOUNDERR</code> (ذي الرمز 1) عند محاولة الانتقال إلى مجلد غير موجود.  
=== ملاحظات خصاصة بالمتصفحات التي تستخدم IndexedDB (فايرفوكس و IE) ===  
=== ملاحظات خاصة بالمنصات التي تستخدم <code>IndexedDB</code> (فايرفوكس و IE) ===  
* الصيغتان <code>.</code> و <code>..</code> غير مدعومتان.  
* الصيغتان <code>.</code> و <code>..</code> غير مدعومتان.  
* لا يدعم المتصفح IE الوضع <code>file:///</code>؛ حيث دعم الوضع المستضاف فقط (http://localhost:xxxx).  
* لا يدعم المتصفح IE العناوين<code>file:///</code>؛ ولكن يدعم الوضع المستضاف فقط (<code><nowiki>http://localhost:xxxx</nowiki></code>).  
* حجم نظام الملفات في فايرفوكس غير محدود، ولكن عند كل تمديد للمساحة بـ 50 ميغابايت، فسيُطلب إذن المستخدم. يتيح المتصفح IE10 ما يصل إلى 10 ميغابايت من AppCache و IndexedDB المُستخدمين في تقيدم نظام الملفات دون المطالبة بالإذن، بمجرد أن تصل إلى هذا المستوى، سيُطلب منك إن كنت تريد السماح بزيادة هذا الحجم إلى 250 ميغابايت كحد أقصى لكل موقغ. لذلك لا يؤثر المعامل <code>size</code> الخاص بالدالة <code>requestFileSystem</code> في نظام الملفات في المتصفحين فايرفوكس و IE.  
* حجم نظام الملفات في فايرفوكس غير محدود، ولكن عند كل تمديد للمساحة إلى 50 ميغابايت، فسيُطلب إذن المستخدم. يتيح المتصفح IE10 إلى حدود 10 ميغابايت من الذاكرتين AppCache و IndexedDB المُستخدمتين في نظام الملفات دون المطالبة بإذن، وبمجرد أن تصل إلى هذا المستوى، سيُطلب منك الإذن لزيادة هذا الحجم إلى 250 ميغابايت كحد أقصى لكل موقع. لذلك، لا يؤثر المعامل <code>size</code> الخاص بالدالة <code>requestFileSystem</code> على نظام الملفات في المتصفحين فايرفوكس و IE.  
* الدالة <code>readAsBinaryString</code> لم تُذكر في المواصفات، وليست مدعومة في المتصفح IE وليس لها تحتوي جذع (stub).  
* الدالة <code>readAsBinaryString</code> لم تُذكر في المواصفات، وليست مدعومة في المتصفح IE، وليس لها جذع (stub).  
* <code>file.type</code> تساوي دائما null.  
* الخاصية <code>file.type</code> تساوي دائما <code>null</code>.  
* عليك ألا تنشئ مُدخلات باستخدام نتيجة دالة الاستجابة (callback) لنسخة DirectoryEntry المحذوفة. وإلا فستحصل على "مُدخلة معلقة" (hanging entry).  
* عليك ألا تنشئ مُدخلات (entries) باستخدام نتيجة دالة الاستجابة (callback) الخاصة بنسخة <code>DirectoryEntry</code> المحذوفة. وإلا فستحصل على مُدخلة مُعلّقة (hanging entry).  
* قبل أن تتمكن من قراءة ملف مكتوب للتو، عليك أن تحصل أولا على نسخة جديدة من ذلك الملف.  
* قبل أن تتمكن من قراءة ملف مكتوب للتّو، عليك أن تحصل أولًا على نسخة جديدة من ذلك الملف.  
* الدالة <code>setMetadata</code>، والتي لم تُذكر في المواصفات، تدعم تغيير الحقل <code>modificationTime</code> فقط.  
* الدالة <code>setMetadata</code>، والتي لم تُذكر في المواصفات، تدعم تغيير الحقل <code>modificationTime</code> فقط.  
* لا تدعم الدالتان <code>copyTo</code> و <code>moveTo</code> المجلدات.  
* لا تدعم الدالتان <code>copyTo</code> و <code>moveTo</code> المجلدات.  
* البيانات الوصفية (metadata) للمجلدات غير مدعومة.  
* البيانات الوصفية (metadata) للمجلدات غير مدعومة.  
* لا يفشل التابعان Entry.remove و directoryEntry.removeRecursively عند إزالة المجلدات غير الفارغة - إذ يتم تنظيف المجلدات المُزالة مع محتوياتها.  
* لا يفشل التابعان <code>Entry.remove</code> و <code>directoryEntry.removeRecursively</code> عند إزالة المجلدات غير الفارغة، إذ يمحوان المجلدات المُزالة مع محتوياتها.  
* الدالتان <code>abort</code> و <code>truncate</code> غير مدعومتان.  
* الدالتان <code>abort</code> و <code>truncate</code> غير مدعومتان.  
* لا يتم إطلاق الأحداث progress. على سبيل المثال، لن يُنفّذ هذا المعالج: <code>javascript
* لا يتم إطلاق أحداث التقدم (progress events). على سبيل المثال، لن يُنفّذ معالج الحدث التالي: <code>javascript writer.onprogress = function() { /*commands*/ };</code>.
writer.onprogress = function() { /*commands*/ };</code>  
 
== ملاحظات حول الترقية ==  
== ملاحظات حول الترقية ==  


في الإصدار 1.0.0 من هذه الإضافة، تغيرت بِنيتَا <code>FileEntry</code> و <code>DirectoryEntry</code>، لتكون أكثر انسجاما مع المواصفات المنشورة.  
في الإصدار 1.0.0 من هذه الإضافة، تغيرت بِنيتَا الكائنين <code>FileEntry</code> و <code>DirectoryEntry</code> لتصبحا أكثر انسجامًا مع المواصفات المنشورة.  


الإصدارات السابقة (قبل 1.0.0) من الإضافة كانت تُخزن device-absolute-file-location في الخاصية <code>fullPath</code> في كائنات <code>Entry</code>. هذه المسارات تبدو عادة كالتالي:  
الإصدارات السابقة (قبل 1.0.0) من الإضافة كانت تُخزن <code>device-absolute-file-location</code> في الخاصية <code>fullPath</code> في الكائن <code>Entry</code>. هذه المسارات تبدو عادةً كالتالي:  
<syntaxhighlight lang="javascript">/var/mobile/Applications/<application UUID>/Documents/path/to/file  (iOS)
<syntaxhighlight lang="javascript">/var/mobile/Applications/<application UUID>/Documents/path/to/file  (iOS)
/storage/emulated/0/path/to/file                                    (Android)‎</syntaxhighlight>  
/storage/emulated/0/path/to/file                                    (Android)‎</syntaxhighlight>  


تُعاد هذه المسارات أيضًا بواسطة التابع <code>toURL()</code> الخاص بالكائنات <code>Entry</code>.  
تُعاد هذه المسارات أيضًا من قبل التابع <code>toURL()</code> الخاص بالكائن <code>Entry</code>.  


في الإصدار v1.0.0، تمثل الخاصية <code>fullPath</code> مسار الملف، نسبةً إلى المجلد الجذري لنظام ملفات HTML. لذلك، سيتم الآن تمثيل كل المسارات المذكورة أعلاه عن طريق الكائن <code>FileEntry</code> كمسار كامل <code>fullPath</code> كالتالي:  
في الإصدار 1.0.0، أصبحت الخاصية <code>fullPath</code> تمثل مسار الملف نسبةً إلى المجلد الجذري لنظام ملفات HTML. لذلك، فالمسارات المذكورة أعلاه سيمثّلها الآن الكائن <code>FileEntry</code> كمسار كامل (الخاصية <code>fullPath</code>) على النحو التالي:  
<syntaxhighlight lang="javascript">/path/to/file‎</syntaxhighlight>  
<syntaxhighlight lang="javascript">/path/to/file‎</syntaxhighlight>  


إن كان تطبيقك يعمل مع device-absolute-paths، وقمت سابقًا باسترداد هذه المسارات عبر الخاصية <code>fullPath</code> من كائنات <code>Entry</code>، فعليك تحديث شيفرتك البرمجية لاستخدام <code>entry.toURL()</code> بدلاً من ذلك.  
إن كان تطبيقك يعمل مع <code>device-absolute-paths</code>، وقمت سابقًا باسترداد هذه المسارات عبر الخاصية <code>fullPath</code> من كائنات <code>Entry</code>، فعليك تحديث شيفرتك البرمجية لاستخدام <code>entry.toURL()</code> بدلًا من ذلك.  


للتوافق مع الإصدارات القديمة، سيقبل التابع <code>resolveLocalFileSystemURL()</code> المعامل device-absolute-path، وسيُعيد كائنًا <code>Entry</code> مقابلًا له، طالما أن الملف موجود داخل أحد نظامي الملفات <code>TEMPORARY</code> أو <code>PERSISTENT</code>.  
للتوافق مع الإصدارات القديمة، سيقبل التابع <code>resolveLocalFileSystemURL()</code> المعامل <code>device-absolute-path</code>، وسيُعيد كائن <code>Entry</code> مقابلًا له، طالما أنّ الملف موجود داخل أحد نظامي الملفات المؤقتة (<code>TEMPORARY</code>) أو المستمرة (<code>PERSISTENT</code>).  


كانت هذه مشكلة خاصة بالإضافة File-Transfer، والتي كانت تستخدم سابقًا مسارات مطلقة للجهاز device-absolute-paths (ولا تزال تقبلها). لقد تم تحديثه لتعمل بشكل صحيح مع روابط نظام الملفات FileSystem URLs، لذا فاستبدال <code>entry.fullPath</code> بـ <code>entry.toURL()</code> سيحل أية مشاكل متعلقة بالإضافة فيما يخص العمل على الملفات الموجودة على الجهاز.  
كانت هذه مشكلة خاصة بالإضافة File-Transfer، إذ كانت تستخدم سابقًا مسارات مطلقة للجهاز <code>device-absolute-paths</code> (ولا تزال تقبلها). وقد تم تحديثها لتعمل بشكل صحيح مع روابط نظام الملفات (FileSystem URLs)، لذلك، فاستبدال <code>entry.fullPath</code> بالتابع <code>entry.toURL()</code> سيحل أية مشاكل قد تواجه الإضافة عند العمل على الملفات الموجودة على الجهاز.  


في الإصدار 1.1.0، تم تغيير القيمة المعادة من الدالة <code>toURL()</code> (انظر [https://issues.apache.org/jira/browse/CB-6394 CB-6394])، إذ باتت تعيد الرابط المطلق "file://‎" ما أمكن. للحصول على رابط داخلي ‎'cdvfile:'‎، يمكنك استخدام التابع <code>toInternalURL()</code>. سيعيد هذه التابع الآن عناوين نظام الملفات وفق الصيغة التالية:  
في الإصدار 1.1.0، تم تغيير القيمة المعادة من الدالة <code>toURL()</code> (انظر الصفحة [https://issues.apache.org/jira/browse/CB-6394 CB-6394])، إذ باتت تعيد الرابط المطلق "<code>file://‎</code>" ما أمكن. للحصول على رابط داخلي ‎'<code>cdvfile:</code>'‎، يمكنك استخدام التابع <code>toInternalURL()</code>. والذي أصبح يعيد عناوين نظام الملفات وفق الصيغة التالية:  
<syntaxhighlight lang="javascript">cdvfile://localhost/persistent/path/to/file‎</syntaxhighlight>  
<syntaxhighlight lang="javascript">cdvfile://localhost/persistent/path/to/file‎</syntaxhighlight>  


والتي يمكن استخدامها لتحديد الملف بدقة.  
يمكن استخدام هذه العناوين لتحديد الملف بدقة.  


== البروتوكول cdvfile ==  
== البروتوكول <code>cdvfile</code> ==  


'''Purpose'''
يمكن استخدام <code>cdvfile://localhost/persistent|temporary|another-fs-root*/path/to/file</code> في مسارات الملفات المستقلة عن المنصة (platform-independent). المسارات <code>cdvfile</code> مدعومة من قبل الإضافات الأساسية (core plugins)؛ فعلى سبيل المثال، يمكنك تنزيل ملف mp3 إلى مسار <code>cdvfile</code> عبر الإضافة <code>cordova-plugin-file-transfer</code> ثم تشغيله عبر الإضافة <code>[[Cordova/cordova plugin media|cordova-plugin-media]]</code>.


يمكن استخدام <code>cdvfile://localhost/persistent|temporary|another-fs-root*/path/to/file</code> في مسارات الملفات المستقلة عن المنصات. مسارات cdvfile مدعومة من قبل الإضافات الأساسية (core plugins)- على سبيل المثال، يمكنك تنزيل ملف mp3 إلى مسار cdvfile عبر الإضافة <code>cordova-plugin-file-transfer</code> ثم تشغيلها عبر الإضافة <code>cordova-plugin-media</code>.  
'''ملاحظة''': راجع الفقرات [[Cordova/cordova plugin file#.D9.85.D9.83.D8.A7.D9.86 .D8.AA.D8.AE.D8.B2.D9.8A.D9.86 .D8.A7.D9.84.D9.85.D9.84.D9.81.D8.A7.D8.AA .28Where to Store Files.29|مكان تخزين الملفات]] و<nowiki/>[[Cordova/cordova plugin file#.D8.A8.D9.86.D9.8A.D8.A7.D8.AA .D9.86.D8.B8.D8.A7.D9.85 .D8.A7.D9.84.D9.85.D9.84.D9.81.D8.A7.D8.AA .28File System Layouts.29|بنيات نظام الملفات]] و<nowiki/>[[Cordova/cordova plugin file#.D8.AA.D8.B9.D8.AF.D9.8A.D9.84 .D8.A5.D8.B9.D8.AF.D8.A7.D8.AF.D8.A7.D8.AA .D8.A7.D9.84.D8.A5.D8.B6.D8.A7.D9.81.D8.A9 .28.D8.A7.D8.AE.D8.AA.D9.8A.D8.A7.D8.B1.D9.8A.29|تعديل إعددات الإضافة]] لمزيد من التفاصيل حول جذور نظام الملفات المتاحة.


'''*Note''': راجع [#where-to-store-files Where to Store Files] و [#file-system-layouts File System Layouts] و [#configuring-the-plugin-optional Configuring the Plugin] لمزيد من التفاصيل حول جذور نظام المفات المتاحة.  
لاستخدام <code>cdvfile</code> كخاصية وَسْمِية <code>src</code>، يمكنك تحويلها إلى مسار أصلي عبر التابع <code>toURL()‎</code> الخاص بالكائن <code>fileEntry</code> الناتج، والذي يمكنك الحصول عليه عبر <code>resolveLocalFileSystemURL</code>؛ راجع الأمثلة أدناه.  


لاستخدام <code>cdvfile</code> كوسم <code>src</code> يمكنك تحويله إلى مسار أصلي عبرالتابع <code>toURL()</code> الخاص بالكائن fileEntry الناتج، والذي يمكنك الحصول عليه عبر <code>resolveLocalFileSystemURL</code> - راجع الأمثلة أدناه.
يمكنك أيضًا استخدام المسارات <code>cdvfile://‎</code> مباشرةً داخل DOM مثل:
<syntaxhighlight lang="xml"><img src="cdvfile://localhost/persistent/img/logo.png" /></syntaxhighlight>  


يمكنك أيضًا استخدام مسارات <code>cdvfile://</code> مباشرةً داخل الشِّعب (DOM)، على سبيل المثال:
'''ملاحظة''': يتطلب هذا التابع تحديثات الأمان التالية:  
<syntaxhighlight lang="javascript"><img src="cdvfile://localhost/persistent/img/logo.png" />‎</syntaxhighlight>
* أضف <code>cdvfile:</code> إلى الوسم الوصفي <code>Content-Security-Policy</code> في صفحة الفهرس، على سبيل المثال:  
 
<syntaxhighlight lang="xml"><meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap:cdvfile:https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *"></syntaxhighlight>
'''Note''': يتطلب هذا التابع تحديثات الأمان التالية:  
* أضف <code><access origin="cdvfile://*" /></code> إلى الملف <code>[[Cordova/config ref|config.xml]]</code>.  
* أضف نظام <code>cdvfile:</code> إلى الوسم الوصفي <code>Content-Security-Policy</code> في صفحة الفهرس، على سبيل المثال:  
مثال عن تحويل <code>cdvfile://</code>'''‎''' إلى مسار أصلي:
* <code><meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap:</code>'''cdvfile:'''<code>https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *"></code>  
* أضف <code><access origin="cdvfile://*" /></code> إلى <code>config.xml</code>.  
 
'''Converting cdvfile:// to native path'''  
<syntaxhighlight lang="javascript">resolveLocalFileSystemURL('cdvfile://localhost/temporary/path/to/file.mp4', function(entry) {
<syntaxhighlight lang="javascript">resolveLocalFileSystemURL('cdvfile://localhost/temporary/path/to/file.mp4', function(entry) {
     var nativePath = entry.toURL();
     var nativePath = entry.toURL();
سطر 503: سطر 508:
     document.getElementById('video').src = nativePath;‎</syntaxhighlight>  
     document.getElementById('video').src = nativePath;‎</syntaxhighlight>  


'''Converting native path to cdvfile://'''  
مثال عن تحويل مسار أصلي إلى <code>cdvfile://</code>'''‎''':
<syntaxhighlight lang="javascript">resolveLocalFileSystemURL(nativePath, function(entry) {
<syntaxhighlight lang="javascript">resolveLocalFileSystemURL(nativePath, function(entry) {
     console.log('cdvfile URI: ' + entry.toInternalURL());‎</syntaxhighlight>  
     console.log('cdvfile URI: ' + entry.toInternalURL());‎</syntaxhighlight>  


'''Using cdvfile in core plugins'''  
مثال حول استخدام <code>cdvfile://</code>'''''' في الإضافات الأساسية:
<syntaxhighlight lang="javascript">fileTransfer.download(uri, 'cdvfile://localhost/temporary/path/to/file.mp3', function (entry) { ...‎</syntaxhighlight>
<syntaxhighlight lang="javascript">fileTransfer.download(uri, 'cdvfile://localhost/temporary/path/to/file.mp3', function (entry) { ...‎</syntaxhighlight>
<syntaxhighlight lang="javascript">var my_media = new Media('cdvfile://localhost/temporary/path/to/file.mp3', ...);
<syntaxhighlight lang="javascript">var my_media = new Media('cdvfile://localhost/temporary/path/to/file.mp3', ...);
my_media.play();‎</syntaxhighlight>
my_media.play();‎</syntaxhighlight>


==== ملاحظات خاصة بنظام الملفات البروتوكول cdvfile ====  
==== ملاحظات خاصة بالبروتوكول cdvfile ====  
* استخدام مسارات <code>cdvfile://</code> في الشِّعب (DOM) غير مدعوم في منصة ويندوز (يمكن تحويل المسار إلى مسار أصلي بدلاً من ذلك).  
* استخدام المسارات <code>cdvfile://</code> في DOM غير مدعوم في منصة ويندوز (يمكن تحويل المسار إلى مسار أصلي لتجاوز ذلك).  


== لائحة أكواد الأخطاء ومعانيها ==  
== لائحة رموز الأخطاء ومعانيها ==  


عند إطلاق خطأ، سيتم استخدام أحد الأكواد التالية.
عند إطلاق خطأ، سيتم استخدام أحد الرموز التالية:
كود  
{| class="wikitable"
ثابتة
!كود الخطأ
1  
!الثابتة
<code>NOT_FOUND_ERR</code>  
|-
2  
|<code>1</code>
<code>SECURITY_ERR</code>  
|<code>NOT_FOUND_ERR</code>
3  
|-
<code>ABORT_ERR</code>  
|<code>2</code>
4  
|<code>SECURITY_ERR</code>
<code>NOT_READABLE_ERR</code>  
|-
5  
|<code>3</code>
<code>ENCODING_ERR</code>  
|<code>ABORT_ERR</code>
6  
|-
<code>NO_MODIFICATION_ALLOWED_ERR</code>  
|<code>4</code>
7  
|<code>NOT_READABLE_ERR</code>
<code>INVALID_STATE_ERR</code>  
|-
8  
|<code>5</code>
<code>SYNTAX_ERR</code>  
|<code>ENCODING_ERR</code>
9  
|-
<code>INVALID_MODIFICATION_ERR</code>  
|<code>6</code>
10  
|<code>NO_MODIFICATION_ALLOWED_ERR</code>
<code>QUOTA_EXCEEDED_ERR</code>  
|-
11  
|<code>7</code>
<code>TYPE_MISMATCH_ERR</code>  
|<code>INVALID_STATE_ERR</code>
12  
|-
<code>PATH_EXISTS_ERR</code>  
|<code>8</code>
|<code>SYNTAX_ERR</code>
|-
|<code>9</code>
|<code>INVALID_MODIFICATION_ERR</code>
|-
|<code>10</code>
|<code>QUOTA_EXCEEDED_ERR</code>
|-
|<code>11</code>
|<code>TYPE_MISMATCH_ERR</code>
|-
|<code>12</code>
|<code>PATH_EXISTS_ERR</code>
|}


== تعديل إعدادات الإضافة (اختياري) ==  
== تعديل إعدادات الإضافة (اختياري) ==  


يمكن تعديل إعدادات أنظمة الملفات المتاحة لكل منصة على حدة. يتعرف كل من منصتي iOS و أندرويد على  
يمكن تعديل إعدادات أنظمة الملفات المتاحة لكل منصة على حدة. تتعرف المنصتان iOS و أندرويد على وسمٍ في الملف <code>[[Cordova/config ref|config.xml]]</code>، والذي يحتوي أسماء أنظمة الملفات المراد تثبيتها. بشكل افتراضي، يتم تمكين كل جذور (roots) نظام الملفات.  
وسم في الملف <code>config.xml</code>، والذي يحتوي أسماء أنظمة الملفات المراد تثبيتها. افتراضيًا، يتم تمكين كل جذور (roots) نظام الملفات.  
<syntaxhighlight lang="xml"><preference name="iosExtraFilesystems" value="library,library-nosync,documents,documents-nosync,cache,bundle,root" />
<syntaxhighlight lang="javascript"><preference name="iosExtraFilesystems" value="library,library-nosync,documents,documents-nosync,cache,bundle,root" />
<preference name="AndroidExtraFilesystems" value="files,files-external,documents,sdcard,cache,cache-external,assets,root" />
<preference name="AndroidExtraFilesystems" value="files,files-external,documents,sdcard,cache,cache-external,assets,root" /></syntaxhighlight>  
</syntaxhighlight>  
===أندرويد===  
===منصة أندرويد===  
* <code>files</code>: مجلد التطبيق المخصص لتخزين الملفات الداخلية
* <code>files</code>: مجلد التخزين الداخلي للملفات.
* <code>files-external</code>: مجلد التطبيق المخصص لتخزين الملفات الخارجية
* <code>files-external</code>: مجلد التخزين الخارجي للملفات.
* <code>sdcard</code>: المجلد لتخزين الملفات الخارجية العامة (والذي سيكون جذر بطاقة الذاكرة SD، إن كانت مُركّبة). يجب أن يكون لديك الإذن <code>android.permission.WRITE_EXTERNAL_STORAGE</code> لاستخدامه.  
* <code>sdcard</code>: مجلد التخزين الخارجي العام للملفات (global external file storage) الذي يساوي جذر بطاقة الذاكرة SD، إن كانت موصولة. يجب أن يكون لديك الإذن <code>android.permission.WRITE_EXTERNAL_STORAGE</code> لاستخدامه.  
* <code>cache</code>: مجلد التخزين المؤقت الداخلي للتطبيق  
* <code>cache</code>: مجلد التخزين المؤقت الداخلي للتطبيق.
* <code>cache-external</code>: مجلد التخزين المؤقت الخارجي للتطبيق  
* <code>cache-external</code>: مجلد التخزين المؤقت الخارجي للتطبيق.
* <code>assets</code>: حزمة (bundle) التطبيق (للقراءة فقط)  
* <code>assets</code>: حزمة (bundle) التطبيق (للقراءة فقط).
* <code>root</code>: نظام ملفات الجهاز بأكمله  
* <code>root</code>: نظام ملفات الجهاز بأكمله.
* <code>applicationDirectory</code>: للقراءة فقط مع وصول مقيد. يمكن نسخ الملفات في هذا المجلد، ولكن في حال محاولة قرائتها مباشرة سينتج عن ذلك تنبيه "<code>file not found</code>". يدعم أندرويد أيضًا نظام ملفات خاص باسم "<code>documents</code>"، والذي يمثل مجلدًا فرعيًا "<code>/Documents/</code>" داخل نظام الملفات "<code>files</code>".
===منصة iOS===
* <code>library</code>: مجلد مكتبة التطبيق.
* <code>documents</code>: مجلد مستندات (Documents) التطبيق.
* <code>cache</code>: مجلد ذاكرة التخزين المؤقت للتطبيق.
* <code>bundle</code>: حزمة التطبيق، وهو موضع التطبيق نفسه على القرص (للقراءة فقط).
* <code>root</code>: نظام ملفات الجهاز بأكمله.


يدعم أندرويد أيضًا نظام ملفات خاص باسم "documents"، والذي يمثل مجلداً فرعيًا "/Documents/" داخل نظام الملفات "files".
افتراضيًا، يمكن مزامنة مجلدي المستندات (documents) والمكتبة (library) مع السحابة iCloud. يمكنك أيضًا طلب (request) نظامي ملفات إضافيين، وهما <code>library-nosync</code> و <code>documents-nosync</code> اللذان يمثلان مجلدًا خاصًا غير متزامن داخل نظام الملفات ‎<code>/Library</code> أو ‎<code>/Documents</code>.
===iOS===
* <code>library</code>: مجلد مكتبة التطبيق
* <code>documents</code>: مجلد مستندات (Documents) التطبيق
* <code>cache</code>: مجلد ذاكرة التخزين المؤقت للتطبيق
* <code>bundle</code>: حزمة التطبيق، موضع التطبيق نفسه على القرص (للقراءة فقط)
* <code>root</code>: نظام ملفات الجهاز بأكمله


افتراضيًا، يمكن مزامنة مجلدي المستندات (documents) والمكتبة (library) مع السحابة iCloud. يمكنك أيضًا طلب نظامي ملفات إضافيين، وهما <code>library-nosync</code> و <code>documents-nosync</code>، واللذان يمثلان مجلدًا خاصًا غير متزامن داخل نظام الملفات <code>/Library</code> أو <code>/Documents</code>.
== مثال عملي ==


== نموذج: إنشاء ملفات والمجلدات، كتابة، قراءة، وإلحاق الملفات ==
تتيح لك إضافة الملفات تنفيذ العديد من الأشياء، مثل تخزين الملفات في موقع تخزين مؤقت أو دائم لأجل استخدامه من قبل تطبيقك (تخزين تجريبي [sandboxed storage])، أو تخزين الملفات في مواقع أخرى بحسب المنصة المُستخدمة. 


تتيح لك الإضافة File تنفيذ أشياء مثل تخزين الملفات في موقع تخزين مؤقت أو دائم لأجل تطبيقك (تخزين مُحصّن [sandboxed storage])، ولتخزين الملفات في مواقع أخرى بحسب على المنصة المُستخدمة. توضح الشيفرات البرمجية في هذا القسم بعض الأمور، مثل:  
توضح الشيفرات البرمجية في هذا القسم بعض هذه الأمور، مثل:  
*[#persistent Accessing the file system]
=== إنشاء ملف دائم ===
* استخدام عناوين (URL) ملفات مستقلة عن المنصات لتخزين ملفاتك [#appendFile store your files] (راجع فقرة مكان تخزين الملفات لمزيد من المعلومات)
* إنشاء [#persistent files] و [#createDir directories]
*[#writeFile Writing to files]
*[#readFile Reading files]
*[#appendFile Appending files]
*[#displayImage Display an image file]


== إنشاء ملف دائم ==
قبل استخدام الواجهات البرمجية لإضافة الملفات، يمكنك الوصول إلى نظام الملفات باستخدام <code>requestFileSystem</code>. عند القيام بذلك، يمكنك طلب استخدام التخزين الدائم أو المؤقت. وفي حال اخترت التخزين الدائم، فلن يُزال إلا بإذن المستخدم.


قبل استخدام الواجهات البرمجية الإضافة الملفات File، يمكنك الوصول إلى نظام الملفات باستخدام <code>requestFileSystem</code>. عند القيام بذلك، يمكنك طلب استخدام التخزين الدائم أو المؤقت. لن يتم إزالة التخزين الدائم إلا بإذن المستخدم.  
عندما تحصل على إذن الوصول إلى نظام الملفات عبر <code>requestFileSystem</code>، يُمنح إذن الوصول لنظام الملفات المقيد في وضع الحماية (sandboxed) فقط (يقيد وضع حجرة الحماية [sandbox] حق الوصول على التطبيق وحده)، ولا يمنح حق الوصول العام إلى أي موضع في نظام الملفات على الجهاز. (للوصول إلى مواضع نظام الملفات الواقعة خارج مساحة التخزين المقيدة له فقط، استخدم توابع أخرى مثل التابع <code>window.resolveLocalFileSystemURL</code>، والذي يدعم المواضع المخصوصة بمنصات معينة. لمثال على ذلك، انظر فقرة "[[Cordova/cordova plugin file#.D8.A5.D8.B6.D8.A7.D9.81.D8.A9 .D9.85.D8.AD.D8.AA.D9.88.D9.89 .D8.A5.D9.84.D9.89 .D9.85.D9.84.D9.81 .D8.A8.D8.A7.D8.B3.D8.AA.D8.AE.D8.AF.D8.A7.D9.85 .D8.AA.D9.88.D8.A7.D8.A8.D8.B9 .D8.A8.D8.AF.D9.8A.D9.84|إضافة محتوى إلى ملف]]".) في هذا المثال تجد طلبًا للتخزين المستمر.  


عندما تحصل على إذن الوصول إلى نظام الملفات عبر <code>requestFileSystem</code>، يُمنح إذن الوصول لنظام الملفات المحصّن (sandboxed) فقط (يقصُر وضع التحصين [sandbox] حق الوصول على التطبيق وحده)، ولا يمنح حق الوصول العام إلى أي موضع في نظام ملفات على الجهاز. (للوصول إلى مواضع نظام الملفات خارج المخزن المُحصّن، استخدم توابع أخرى مثل window.resolveLocalFileSystemURL، والذي يدعم المواضع المخصوصة بمنصات معينة. لمثال على ذلك، انظر فقرة إلحاق ملف.)  
'''ملاحظة''': عند استهداف عملاء [[Cordova/webviews|العارض WebView]] (بدلًا من المتصفح)، أو التطبيقات الأصلية (ويندوز)، فلا تحتاج إلى استخدام <code>requestQuota</code> قبل استخدام التخزين الدائم.  
<syntaxhighlight lang="javascript">window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fs) {


هنا طلبٌ للتخزين المستمر.
ملاحظة: عند استهداف عملاء [[Cordova/webviews|العارض]] WebView (بدلاً من المتصفح) أو التطبيقات الأصلية (ويندوز)، فلا تحتاج إلى استخدام <code>requestQuota</code> قبل استخدام التخزين الدائم.
<syntaxhighlight lang="javascript">window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fs) {
     console.log('file system open: ' + fs.name);
     console.log('file system open: ' + fs.name);
     fs.root.getFile("newPersistentFile.txt", { create: true, exclusive: false }, function (fileEntry) {
     fs.root.getFile("newPersistentFile.txt", { create: true, exclusive: false }, function (fileEntry) {
         console.log("fileEntry is file?" + fileEntry.isFile.toString());
         console.log("fileEntry is file?" + fileEntry.isFile.toString());
         // fileEntry.name == 'someFile.txt'
         // fileEntry.name == 'someFile.txt'
         // fileEntry.fullPath == '/someFile.txt'
         // fileEntry.fullPath == '/someFile.txt'
         writeFile(fileEntry, null);
         writeFile(fileEntry, null);
     }, onErrorCreateFile);
     }, onErrorCreateFile);
}, onErrorLoadFs);‎</syntaxhighlight>


تتلقى دالة النجاح (success callback) كائنًا FileSystem. استخدم <code>fs.root</code> لإعادة كائنٍ DirectoryEntry، والذي يمكنك استخدامه لإنشاء أو الحصول على ملف (عن طريق استدعاء <code>getFile</code>). في هذا المثال، <code>fs.root</code> هو كائنٌ DirectoryEntry يمثل التخزين الدائم في نظام الملفات المُحصّن.  
}, onErrorLoadFs);</syntaxhighlight>
 
تتلقى دالة رد نداء النجاح (success callback) الكائن <code>FileSystem</code>. إن أردت إعادة كائنٍ <code>DirectoryEntry</code>، فاستخدم <code>fs.root</code>، والذي يمكنك استخدامه لإنشاء أو الحصول على ملف (عن طريق استدعاء التابع <code>getFile</code>). يمثل <code>fs.root</code> في هذا المثال كائنًا <code>DirectoryEntry</code>، والذي يمثل التخزين الدائم في نظام الملفات المقيد (sandboxed file system).  


تتلقى دالة النجاح (success callback) الخاصة بالتابع <code>getFile</code> كائناً FileEntry. يمكنك استخدام هذا لتنفيذ عمليات الكتابة والقراءة على الملف.  
تتلقى دالة رد نداء النجاح (success callback) الخاصة بالتابع <code>getFile</code> الكائن <code>FileEntry</code>. الذي يمكنك استخدامه لتنفيذ عمليات الكتابة والقراءة على الملف.  


== إنشاء ملف مؤقت ==  
=== إنشاء ملف مؤقت ===  


في ما يلي مثال لطلب تخزينٍ مؤقت. قد يتم حذف التخزين المؤقت من قبل نظام التشغيل في حال انحسار ذاكرة الجهاز.  
في ما يلي مثال لطلب تخزينٍ مؤقت. تذكّر أنه قد يتم حذف التخزين المؤقت من قبل نظام التشغيل في حال انحسار ذاكرة الجهاز.  
<syntaxhighlight lang="javascript">window.requestFileSystem(window.TEMPORARY, 5 * 1024 * 1024, function (fs) {
<syntaxhighlight lang="javascript">window.requestFileSystem(window.TEMPORARY, 5 * 1024 * 1024, function (fs) {
     console.log('file system open: ' + fs.name);
     console.log('file system open: ' + fs.name);
     createFile(fs.root, "newTempFile.txt", false);
     createFile(fs.root, "newTempFile.txt", false);
}, onErrorLoadFs);‎</syntaxhighlight>


عندما تستخدم التخزين المؤقت، يمكنك إنشاء أو الحصول على الملف عن طريق استدعاء التابع <code>getFile</code>. كما في مثال التخزين الثابت، سيعطيك هذا كائنًا FileEntry، والذي يمكنك استخدامه لأجل عمليات القراءة أو الكتابة.  
}, onErrorLoadFs);</syntaxhighlight>
 
عندما تستخدم التخزين المؤقت، يمكنك إنشاء أو الحصول على الملف عن طريق استدعاء التابع <code>getFile</code>. وكما في مثال التخزين المستمر، سيعطيك هذا الكائن <code>FileEntry</code> الذي يمكنك استخدامه في عمليات القراءة أو الكتابة.  
<syntaxhighlight lang="javascript">function createFile(dirEntry, fileName, isAppend) {
<syntaxhighlight lang="javascript">function createFile(dirEntry, fileName, isAppend) {
     // Creates a new file or returns the file if it already exists.
     // انشاء ملف جديد أو إعادة الملف إن كان موجودا سلفا
     dirEntry.getFile(fileName, {create: true, exclusive: false}, function(fileEntry) {
     dirEntry.getFile(fileName, {create: true, exclusive: false}, function(fileEntry) {
         writeFile(fileEntry, null, isAppend);
         writeFile(fileEntry, null, isAppend);
سطر 619: سطر 637:
}‎</syntaxhighlight>  
}‎</syntaxhighlight>  


== الكتابة في ملف ==  
=== الكتابة في ملف ===  


بمجرد أن يكون لديك كائن FileEntry، يمكنك الكتابة في الملف عن طريق استدعاء <code>createWriter</code>، والذي يعيد كائنًا FileWriter في دالة النجاح. استدع التابع <code>write</code> الخاص بالكائن FileWriter للكتابة إلى الملف.  
بمجرد الحصول على الكائن <code>FileEntry</code>، يمكنك الكتابة في الملف عن طريق استدعاء التابع <code>createWriter</code>، والذي يعيد الكائن <code>FileWriter</code> في دالة رد نداء النجاح (success callback).
 
استدع التابع <code>write</code> الخاص بالكائن <code>FileWriter</code> للكتابة في الملف.  
<syntaxhighlight lang="javascript">function writeFile(fileEntry, dataObj) {
<syntaxhighlight lang="javascript">function writeFile(fileEntry, dataObj) {
     // Create a FileWriter object for our FileEntry (log.txt).
     // (log.txt) FileEntry لأجل الكائن FileWriter انشاء
     fileEntry.createWriter(function (fileWriter) {
     fileEntry.createWriter(function (fileWriter) {
         fileWriter.onwriteend = function() {
         fileWriter.onwriteend = function() {
سطر 632: سطر 652:
             console.log("Failed file write: " + e.toString());
             console.log("Failed file write: " + e.toString());
         };
         };
         // If data object is not passed in,
         // dataObj  في حال عدم تمرير كائن البيانات
         // create a new Blob instead.
         // جديد Blob أنشئ كائن.
         if (!dataObj) {
         if (!dataObj) {
             dataObj = new Blob(['some file data'], { type: 'text/plain' });
             dataObj = new Blob(['some file data'], { type: 'text/plain' });
سطر 641: سطر 661:
}‎</syntaxhighlight>  
}‎</syntaxhighlight>  


== قراءة الملف ==  
=== قراءة ملف ===  


تحتاج إلى كائن FileEntry لقراءة ملف موجود. استخدم الخاصية file في الكائن FileEntry للحصول على مرجع الملف، ثم أنشئ كائنًا جديدًا من النوع FileReader. يمكنك استخدام توابع مثل <code>readAsText</code> لبدء عملية القراءة. عند اكتمال عملية القراءة، سيخزن <code>this.result</code> نتيجة عملية القراءة.  
تحتاج إلى الكائن <code>FileEntry</code> لقراءة ملف موجود. استخدم الخاصية <code>file</code> في الكائن <code>FileEntry</code> للحصول على مرجع الملف، ثم أنشئ كائنًا جديدًا من النوع <code>FileReader</code>. يمكنك استخدام توابع مثل التابع <code>readAsText</code> لبدء عملية القراءة.
 
عند اكتمال عملية القراءة، ستخزن الخاصيةُ <code>this.result</code> نتيجةَ عمليةِ القراءة.  
<syntaxhighlight lang="javascript">function readFile(fileEntry) {
<syntaxhighlight lang="javascript">function readFile(fileEntry) {
     fileEntry.file(function (file) {
     fileEntry.file(function (file) {
سطر 655: سطر 677:
}‎</syntaxhighlight>  
}‎</syntaxhighlight>  


== الإضافة إلى محتوى ملف باستخدام أساليب بديلة ==  
=== إضافة محتوى إلى ملف باستخدام طرق بديلة ===  


بالطبع، ستحتاج غالبًا إلى إضافة محتوى إلى الملفات الموجودة بدلاً من إنشاء ملفات جديدة. إليك مثالًا على ذلك. يوضح هذا المثال طريقة أخرى يمكنك من خلالها الوصول إلى نظام الملفات باستخدام window.resolveLocalFileSystemURL. في هذا المثال، قم بتمرير عنوان الملف المستقل عن المنصات، cordova.file.dataDirectory، إلى الدالة. تتلقى دالة النجاح (success callback) كائنًا DirectoryEntry، والذي يمكنك استخدامه لإنشاء ملف وغير ذلك من الأمور.  
ستحتاج غالبًا إلى إضافة محتوًى إلى الملفات الموجودة بدلًا من إنشاء ملفات جديدة. إليك مثالًا على ذلك.
 
يوضح هذا المثال طريقة أخرى يمكنك من خلالها الوصول إلى نظام الملفات باستخدام <code>window.resolveLocalFileSystemURL</code>. في هذا المثال، ستقوم بتمرير عنوان الملف المستقل عن المنصات <code>cordova.file.dataDirectory</code> إلى الدالة. تتلقى دالة رد نداء النجاح (success callback) كائنًا من النوع <code>DirectoryEntry</code> الذي يمكنك استخدامه للقيام بعدة أمور  مثل إنشاء ملفٍ وما شابه.  
<syntaxhighlight lang="javascript">window.resolveLocalFileSystemURL(cordova.file.dataDirectory, function (dirEntry) {
<syntaxhighlight lang="javascript">window.resolveLocalFileSystemURL(cordova.file.dataDirectory, function (dirEntry) {
     console.log('file system open: ' + dirEntry.name);
     console.log('file system open: ' + dirEntry.name);
سطر 664: سطر 688:
}, onErrorLoadFs);‎</syntaxhighlight>  
}, onErrorLoadFs);‎</syntaxhighlight>  


بالإضافة إلى هذا الاستخدام، يمكنك استخدام التابع <code>resolveLocalFileSystemURL</code> للوصول إلى بعض مواضع نظام الملفات التي لا تدخل في نظام التخزين المحصّن. راجع فقرة مكان تخزين الملفات لمزيد من المعلومات؛ العديد من مواقع التخزين هذه مخصوصة بالمنصات. يمكنك أيضًا تمرير مواضع نظام ملفات مستقلة عن المنصات إلى التابع <code>resolveLocalFileSystemURL</code> باستخدام البروتوكول cdvfile.  
بالإضافة إلى هذا، يمكنك استخدام التابع <code>resolveLocalFileSystemURL</code> للوصول إلى بعض مواضع نظام الملفات التي لا تدخل في نظام التخزين المقيَّد. راجع قسم [[Cordova/cordova plugin file#.D9.85.D9.83.D8.A7.D9.86 .D8.AA.D8.AE.D8.B2.D9.8A.D9.86 .D8.A7.D9.84.D9.85.D9.84.D9.81.D8.A7.D8.AA .28Where to Store Files.29|مكان تخزين الملفات]] لمزيد من المعلومات؛ العديد من مواضع التخزين هذه مخصوصة بالمنصات. يمكنك أيضًا تمرير مواضع نظام ملفات مستقلة عن المنصات إلى التابع <code>resolveLocalFileSystemURL</code> باستخدام البروتوكول <code>cdvfile</code>.
 
بالنسبة إلى عملية الإضافة (append)، لا يوجد شيء جديد في الدالة <code>createFile</code> التي استدعيناها في الشيفرة البرمجية السابقة (راجع الأمثلة السابقة لمطالعة الشيفرات الفعلية). حيث تستدعي <code>createFile</code> الدالة <code>writeFile</code>. لكن عليك أن تتحقق من <code>writeFile</code> مما إذا كانت عملية الإضافة مطلوبة أم لا.  


بالنسبة إلى عملية الإضافة (append)، لا يوجد شيء جديد في الدالة <code>createFile</code> التي استدعيت في الشيفرة البرمجية السابقة (راجع الأمثلة السابقة لمطالعة الشيفرات الفعلية). الدالة <code>createFile</code> تستدعي <code>writeFile</code>. عليك أن تتحقق في <code>writeFile</code> مما إذا كانت عملية الإضافة مطلوبة.  
بمجرد الحصول على الكائن <code>FileWriter</code>، استدعِ التابع <code>seek</code>، ومرّر إليه فهرس الموضع الذي تريد الكتابة عنده.


بمجرد الحصول على كائن FileWriter، استدع التابع <code>seek</code>، ومرّر إليه فهرس الموضع الذي تريد الكتابة عنده. في هذا المثال، عليك أيضًا التحقق من وجود الملف. بعد استدعاء التابع seek، استدع التابع write الخاصة بالكائن FileWriter.  
في هذا المثال، سنتحقق أيضًا من وجود الملف. وبعد استدعاء التابع <code>seek</code>، سنستدعي التابع <code>write</code> الخاص بالكائن <code>FileWriter</code>.  
<syntaxhighlight lang="javascript">function writeFile(fileEntry, dataObj, isAppend) {
<syntaxhighlight lang="javascript">function writeFile(fileEntry, dataObj, isAppend) {
     // Create a FileWriter object for our FileEntry (log.txt).
     // (log.txt) FileEntry لأجل الكائن FileWriter انشاء
     fileEntry.createWriter(function (fileWriter) {
     fileEntry.createWriter(function (fileWriter) {
         fileWriter.onwriteend = function() {
         fileWriter.onwriteend = function() {
سطر 679: سطر 705:
             console.log("Failed file read: " + e.toString());
             console.log("Failed file read: " + e.toString());
         };
         };
         // If we are appending data to file, go to the end of the file.
         // في حال إضافة بيانات إلى الملف، اذهب إلى نهاية الملف
         if (isAppend) {
         if (isAppend) {
             try {
             try {
سطر 692: سطر 718:
}‎</syntaxhighlight>  
}‎</syntaxhighlight>  


== تخزين ملف ثنائي موجود ==  
=== تخزين ملف ثنائي موجود (Store an existing binary file) ===
 
سبق ووضحنا كيفية الكتابة في ملف أنشأته للتو في نظام الملفات المقيد. لكن ماذا لو احتجت إلى الوصول إلى ملف موجود، وأردت جعله قابلًا للتخزين على جهازك؟ في هذا المثال، ستحصل على ملف باستخدام طلبية xhr ‏(xhr request‏)، ثم ستحفظه في ذاكرة التخزين المؤقت في نظام الملفات المُحصّنة.


سبق ووضحنا كيفية الكتابة في ملف أنشأته للتو في نظام الملفات المُحصّن. ماذا لو احتجت إلى الوصول إلى ملف موجود وجعله قابلًا للتخزين على جهازك؟ في هذا المثال، ستحصل على ملف باستخدام طلبية xhr، ثم ستحفظه في ذاكرة التخزين المؤقت في نظام الملفات المُحصّنة.  
قبل الحصول على الملف، عليك الحصول أولًا على مرجع لكائن <code>FileSystem</code> باستخدام التابع <code>requestFileSystem</code>. مع إعطائه القيمة <code>window.TEMPORARY</code> (كما فعلنا من قبل)، يمثل الكائن <code>FileSystem</code> المعاد ذاكرة التخزين المؤقت في نظام الملفات المقيِّد.


قبل الحصول على الملف، احصل على مرجع لكائن FileSystem باستخدام التابع <code>requestFileSystem</code>. ومرّر إليهwindow.TEMPORARY (كما فعلنا من قبل)، يمثل الكائن FileSystem المعاد ذاكرة التخزين المؤقت في نظام االملفات المُحصّنة. استخدم <code>fs.root</code> للحصول على كائن DirectoryEntry الذي تحتاجه.  
استخدم <code>fs.root</code> للحصول على الكائن <code>DirectoryEntry</code> الذي تحتاجه.  
<syntaxhighlight lang="javascript">window.requestFileSystem(window.TEMPORARY, 5 * 1024 * 1024, function (fs) {
<syntaxhighlight lang="javascript">window.requestFileSystem(window.TEMPORARY, 5 * 1024 * 1024, function (fs) {
     console.log('file system open: ' + fs.name);
     console.log('file system open: ' + fs.name);
سطر 702: سطر 730:
}, onErrorLoadFs);‎</syntaxhighlight>  
}, onErrorLoadFs);‎</syntaxhighlight>  


في الختام، إليك طلبية xhr للحصول على بقعة الصورة (Blob image). لا يوجد أي شيء خاص بكوردوفا في هذه الشيفرة، باستثناء أنك ستقوم إعادة توجيه مرجع DirectoryEntry الذي حصلت عليه بالفعل كوسيط للدالة saveFile. سوف تقوم بحفظ بقعة الصورة (Blob image) وعرضها في وقت لاحق بعد قراءة الملف (للتحقق من صحة العملية).  
في الختام، إليك طلبية xhr للحصول على الصورة Blob. لا يوجد أي شيء خاص بكوردوفا في هذه الشيفرة، باستثناء أنك ستقوم بإعادة توجيه مرجع <code>DirectoryEntry</code> الذي حصلت عليه بالفعل إلى الدالة <code>saveFile</code> كوسيط. سوف تقوم بحفظ الصورة وعرضها في وقت لاحق بعد قراءة الملف (للتحقق من صحة العملية).  
<syntaxhighlight lang="javascript">function getSampleFile(dirEntry) {
<syntaxhighlight lang="javascript">function getSampleFile(dirEntry) {
     var xhr = new XMLHttpRequest();
     var xhr = new XMLHttpRequest();
سطر 715: سطر 743:
     xhr.send();
     xhr.send();
}‎</syntaxhighlight>  
}‎</syntaxhighlight>  
ملاحظة: كجزء من إجراءات الأمان في كوردوفا 5، تتطلب الشيفرة السابقة إضافة اسم النطاق، http://cordova.apache.org، إلى العنصر Content-Security-Policy  
'''ملاحظة''': كجزء من إجراءات الأمان في كوردوفا 5، تتطلب الشيفرة السابقة إضافة اسم النطاق، [http://cordova.apache.org، http://cordova.apache.org]، إلى العنصر <code>Content-Security-Policy</code> في الملف <code>index.html</code>.  
في الملف index.html.  


بعد الحصول على الملف، انسخ المحتويات في ملف جديد. الكائن DirectoryEntry الحالي مرتبط بالفعل مع التخزين المؤقت للتطبيق.  
بعد الحصول على الملف، انسخ المحتويات في ملف جديد. الكائن <code>DirectoryEntry</code> الحالي مرتبط بالفعل مع المخزن المؤقت (cache) للتطبيق.  
<syntaxhighlight lang="javascript">function saveFile(dirEntry, fileData, fileName) {
<syntaxhighlight lang="javascript">function saveFile(dirEntry, fileData, fileName) {
     dirEntry.getFile(fileName, { create: true, exclusive: false }, function (fileEntry) {
     dirEntry.getFile(fileName, { create: true, exclusive: false }, function (fileEntry) {
سطر 725: سطر 752:
}‎</syntaxhighlight>  
}‎</syntaxhighlight>  


في writeFile، يمكنك تمرير في كائن الملف Blob باعتباره dataObj، وستحفظه في الملف الجديد.  
ستمرر كائن الملف Blob إلى الدالة <code>writeFile</code> باعتباره كائن البيانات <code>dataObj</code>، وستحفظه في الملف الجديد.  
<syntaxhighlight lang="javascript">function writeFile(fileEntry, dataObj, isAppend) {
<syntaxhighlight lang="javascript">function writeFile(fileEntry, dataObj, isAppend) {
     // Create a FileWriter object for our FileEntry (log.txt).
     // (log.txt) FileEntry لأجل الكائن FileWriter انشاء
     fileEntry.createWriter(function (fileWriter) {
     fileEntry.createWriter(function (fileWriter) {
         fileWriter.onwriteend = function() {
         fileWriter.onwriteend = function() {
سطر 745: سطر 772:
}‎</syntaxhighlight>  
}‎</syntaxhighlight>  


بعد الكتابة في الملف، اقرأه وقم بعرضه. لقد حفظت الصورة كبيانات ثنائية (binary data)، حتى تتمكن من قراءتها باستخدام التابع FileReader.readAsArrayBuffer.  
بعد الكتابة في الملف، اقرأه وقم بعرضه. وبما أنّك حفظت الصورة على هيئة بيانات ثنائية (binary data)، فيمكنك قراءتها باستخدام التابع <code>FileReader.readAsArrayBuffer</code>.  
<syntaxhighlight lang="javascript">function readBinaryFile(fileEntry) {
<syntaxhighlight lang="javascript">function readBinaryFile(fileEntry) {
     fileEntry.file(function (file) {
     fileEntry.file(function (file) {
سطر 759: سطر 786:
}‎</syntaxhighlight>  
}‎</syntaxhighlight>  


بعد قراءة البيانات، يمكنك عرض الصورة باستخدام الشيفرة التالية. استخدم window.URL.createObjectURL للحصول على السلسلة النصية للشِّعب (DOM) الخاصة ببقعة الصورة (Blob image).  
بعد قراءة البيانات، يمكنك عرض الصورة باستخدام الشيفرة الموضحة في المثال التالي. استخدم <code>window.URL.createObjectURL</code> للحصول على السلسلة النصية DOM الخاصة بالصورة Blob.  
<syntaxhighlight lang="javascript">function displayImage(blob) {
<syntaxhighlight lang="javascript">function displayImage(blob) {
     // Displays image if result is a valid DOM string for an image.
     // استخدم الصورة إن كانت النتيجة عبارة عن
    // DOM سلسلة نصية تمثل صورة صالحة في
     var elem = document.getElementById('imageFile');
     var elem = document.getElementById('imageFile');
     // Note: Use window.URL.revokeObjectURL when finished with image.
     // عند إنهاء الصورة window.URL.revokeObjectURL ملاحظة:استخدم
     elem.src = window.URL.createObjectURL(blob);
     elem.src = window.URL.createObjectURL(blob);
}‎</syntaxhighlight>  
}‎</syntaxhighlight>  


== عرض ملف صورة ==  
=== عرض ملف صورة ===  


لعرض صورة باستخدام FileEntry، يمكنك استدعاء التابع <code>toURL</code>.
لعرض صورة باستخدام <code>FileEntry</code>، يمكنك استدعاء التابع <code>toURL</code> بالشكل التالي:
<syntaxhighlight lang="javascript">function displayImageByFileURL(fileEntry) {
<syntaxhighlight lang="javascript">function displayImageByFileURL(fileEntry) {
     var elem = document.getElementById('imageFile');
     var elem = document.getElementById('imageFile');
سطر 775: سطر 803:
}‎</syntaxhighlight>  
}‎</syntaxhighlight>  


إن كنت تستخدم عناوين مخصوصة بمنصات معينة بدلاً من FileEntry، وأردت عرض صورة، فقد تحتاج إلى تضمين الجزء الرئيسي من العنوان URI في العنصر Content-Security-Policy  
إن كنت تستخدم عناوين مخصوصة بمنصات معينة بدلًا من <code>FileEntry</code>، وأردت عرض صورة، فقد تحتاج إلى تضمين الجزء الرئيسي من العنوان في العنصر <code>Content-Security-Policy</code> في الملف <code>index.html</code>.
في الملف index.html. على سبيل المثال، في ويندوز 10، يمكنك تضمين <code>ms-appdata:</code> في  
 
ذلك العنصر. إليك المثال التالي:  
على سبيل المثال، في ويندوز 10، يمكنك تضمين <code>ms-appdata:</code> في ذلك العنصر. كما يوضح المثال التالي:  
<syntaxhighlight lang="javascript"><meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: ms-appdata: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">‎</syntaxhighlight>  
<syntaxhighlight lang="javascript"><meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: ms-appdata: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">‎</syntaxhighlight>  


== إنشاء المجلدات ==  
=== إنشاء المجلدات ===  


في الشفرة التالية، ستنشئ مجلدات في جذر موضع التخزين الخاص بالتطبيق. يمكنك استخدام هذه الشيفرة مع أي موضع تخزين قابل للكتابة (DirectoryEntry). في هذا المثال، ستكتب في ذاكرة التخزين المؤقت للتطبيق (على افتراض أنك استخدمت window.TEMPORARY للحصول على الكائن FileSystem) عن طريق تمرير fs.root إلى هذه الدالة.  
في الشيفرة التالية، ستنشئ مجلدات في المجلد الجذري للمخزن (root storage location) الخاص بالتطبيق. يمكنك استخدام هذه الشيفرة مع أي موضع تخزين قابل للكتابة (<code>DirectoryEntry</code>). في هذا المثال، ستكتب في ذاكرة التخزين المؤقت للتطبيق (على افتراض أنك حصلت على الكائن <code>FileSystem</code> عبر <code>window.TEMPORARY</code> ) عن طريق تمرير <code>fs.root</code> إلى هذه الدالة.  


ننشئ هذه الشيفرة المجلد ‎/NewDirInRoot/images في ذاكرة التخزين المؤقت للتطبيق. بخصوص القيم المخصوصة بمنصات معينة، راجع فقرات بنيات نظام الملفات أعلاه.  
تنشئ هذه الشيفرة المجلد <code>‎/NewDirInRoot/images‎</code> في المخزن المؤقت للتطبيق (بخصوص القيم المخصوصة بمنصات معينة، راجع فقرة [[Cordova/cordova plugin file#.D8.A8.D9.86.D9.8A.D8.A7.D8.AA .D9.86.D8.B8.D8.A7.D9.85 .D8.A7.D9.84.D9.85.D9.84.D9.81.D8.A7.D8.AA .28File System Layouts.29|تخطيط نظام الملفات]] أعلاه).  
<syntaxhighlight lang="javascript">function createDirectory(rootDirEntry) {
<syntaxhighlight lang="javascript">function createDirectory(rootDirEntry) {
     rootDirEntry.getDirectory('NewDirInRoot', { create: true }, function (dirEntry) {
     rootDirEntry.getDirectory('NewDirInRoot', { create: true }, function (dirEntry) {
سطر 794: سطر 822:


عند إنشاء مجلدات فرعية، عليك إنشاء كل مجلد على حدة كما هو موضح في الشيفرة البرمجية السابقة.
عند إنشاء مجلدات فرعية، عليك إنشاء كل مجلد على حدة كما هو موضح في الشيفرة البرمجية السابقة.
== انظر أيضًا ==
* إضافة [[Cordova/cordova plugin device|حالة الجهاز]]
* إضافة [[Cordova/cordova plugin geolocation|تحديد الموقع الجغرافي]]
* [[Cordova/config ref|الملف Config.xml]]
* [[Cordova/plugins|دليل تطوير الإضافات في كوردوفا]]
==مصادر==
==مصادر==
*[https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-file/index.html صفحة cordova-plugin-file في توثيق كوردوفا الرسمي.]
*[https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-file/index.html صفحة cordova-plugin-file في توثيق كوردوفا الرسمي.]

المراجعة الحالية بتاريخ 08:48، 23 يونيو 2022

تقدم إضافة الملفات (cordova-plugin-file) واجهة برمجية للملفات، والتي يمكن استخدامها للقراءة أو الكتابة في الملفات الموجودة على الجهاز.

هذه الإضافة مبنية على عدة مواصفات، منها:

دورة تطوير التطبيقات باستخدام لغة JavaScript
  • 71 ساعة فيديو تدريبية
  • من الصفر دون الحاجة لخبرة مسبقة
  • شهادة معتمدة من أكاديمية حسوب
  • متابعة أثناء الدورة من فريق مختص

ملاحظة: رغم أن مواصفات W3C FileSystem أصبحت مهملة في متصفحات الويب، إلا أنّ كوردوفا تدعمها عبر هذه الإضافة في المنصات المدرجة في فقرة المنصات المدعومة، باستثناء المتصفحات (Browser).

لفهم كيفية استخدام هذه الإضافة، تحقق من المثال في أسفل هذه الصفحة. ولمزيد من الأمثلة (المرتكزة على المتصفحات)، يمكنك الاطلاع على هذا المقال الرائع حول FileSystem .

للتعرف على خيارات التخزين الأخرى، يرجى الرجوع إلى دليل التخزين.

تعرّف إضافة الملفات كائنًا عامًّا هو cordova.file الذي على الرغم من كونه موجودًا في النطاق العام (global scope)، إلا أنه لن يكون متوفرًا إلا بعد إطلاق الحدث deviceready.

document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
    console.log(cordova.file);
}

التثبيت

يمكنك تثبيت هذه الإضافة عبر الأمر:

cordova plugin add cordova-plugin-file‎

المنصات المدعومة

  • أندرويد
  • iOS
  • OS X
  • ويندوز*
  • Browser

* لا تدعم هذه المنصات التابعين FileReader.readAsArrayBuffer و FileWriter.write(blob)‎.

مكان تخزين الملفات

بدءًا من الإصدار 1.2.0، صار استخدام العناوين URL للمجلدات المهمة في نظام الملفات متاحًا. تلك العناوين مُصاغة وفق الشكل التالي: file:///path/to/spot/‎، ويمكن تحويلها إلى الكائن DirectoryEntry باستخدام التابع window.resolveLocalFileSystemURL()‎.

  • cordova.file.applicationDirectory - المجلد الذي ثُبِّت فيه التطبيق، وهو للقراءة فقط. (iOS، أندرويد، BlackBerry 10، OSX، ويندوز)
  • cordova.file.applicationStorageDirectory - المجلد الجذري لبيئة التطبيق التجريبية (application's sandbox)؛ على منصتي iOS وويندوز، يكون هذا المجلد للقراءة فقط (لكن بعض المجلدات الفرعية، مثل ‎/Documents في منصة iOS أو ‎/localState في ويندوز، قابلة للقراءة والكتابة معًا). جميع البيانات المضمنة داخل هذا المجلد ستبقى مخصوصة بالتطبيق. (iOS وأندرويد و BlackBerry 10 و OSX)
  • cordova.file.dataDirectory - مجلد لتخزين البيانات الدائمة والخاصة داخل بيئة التطبيق التجريبية (application's sandbox) باستخدام الذاكرة الداخلية (على منصة أندرويد، إن كنت بحاجة إلى استخدام ذاكرة خارجية، فاستخدم ‎.externalDataDirector). على منصة iOS، لا يُزامَن هذا المجلد مع السحابة iCloud (استخدم لأجل ذلك ‎.syncedDataDirectory). (ويندوز، أندرويد، iOS و BlackBerry 10)
  • cordova.file.cacheDirectory - مجلد للتخزين المؤقت لملفات البيانات، أو الملفات التي يمكن للتطبيق إعادة إنشائها بسهولة. قد يحذف نظام التشغيل هذه الملفات عندما يشعر بانحسار ذاكرة الجهاز، ولكن يجب ألا يعوِّل تطبيقك على نظام التشغيل لحذف الملفات الموجودة في هذا المجلد. (iOS، أندرويد، BlackBerry 10، OSX، ويندوز)
  • cordova.file.externalApplicationStorageDirectory - مساحة التطبيق على وحدة التخزين الخارجية (external storage). (أندرويد)
  • cordova.file.externalDataDirectory - المجلد الذي ستوضع فيه ملفات البيانات الخاصة بالتطبيق على وحدة التخزين الخارجية. (أندرويد)
  • cordova.file.externalCacheDirectory - ذاكرة التخزين المؤقت للتطبيق في وحدة التخزين الخارجية. (أندرويد)
  • cordova.file.externalRootDirectory - المجلد الجذري (root) لوحدة التخزين الخارجية (بطاقة SD). (أندرويد، BlackBerry 10)
  • cordova.file.tempDirectory - مجلد يضم الملفات المؤقتة التي يمكن لنظام التشغيل مسحها في أي وقت. لا تعتمد على نظام التشغيل لمحو محتويات هذا المجلد. يجب أن يزيل تطبيقك دائمًا الملفات الموجودة في هذا المجلد بحسب الحاجة. (iOS ،OSX، ويندوز)
  • cordova.file.syncedDataDirectory - يحتوي هذا المجلد ملفات التطبيق التي يجب مزامنتها (مثلًا، مع السحابة iCloud). (ويندوز، iOS)
  • cordova.file.documentsDirectory - يضم هذا المجلد الملفات الخاصة بالتطبيق، والتي لها أهمية للتطبيقات الأخرى (مثل ملفات Office). لاحظ أنه في منصة OSX، هذا المجلد هو مجلد المستخدم ‎~/Documents. ‏(iOS، OSX)
  • cordova.file.sharedDirectory - يحتوي هذا المجلد على الملفات المتاحة لجميع التطبيقات. (BlackBerry 10)

تخطيط نظام الملفات (File System Layouts)

على الرغم من أن تخطيط نظام الملفات من الناحية الفنية تُعد من تفاصيل التقديم (implementation)، إلا أنه قد يكون من المفيد معرفة كيفية الربط بين الخاصيات cordova.file.*‎ وبين المسارات الفعلية على الجهاز الحقيقي.

بنية نظام الملفات في منصة iOS

مسار الجهاز cordova.file.*‎ iosExtraFileSystems كتابة/قراءة؟ مستمرة؟ أيمحوه نظام التشغيل؟ مزامنة خاص
‎/var/mobile

/Applications/<UUID>/‎

applicationStorageDirectory - ق غ/م غ/م غ/م نعم
appname.app/‎ applicationDirectory bundle ق غ/م غ/م غ/م نعم
www/ - - ق غ/م غ/م غ/م نعم
Documents/‎ documentsDirectory documents ق/ك نعم لا نعم نعم
NoCloud/‎ - documents-nosync ق/ك نعم لا لا نعم
Library - library ق/ك نعم لا نعم؟ نعم
NoCloud/‎ dataDirectory library-nosync ق/ك نعم لا لا نعم
Cloud/‎ syncedDataDirectory - ق/ك نعم لا نعم نعم
Caches/‎ cacheDirectory cache ق/ك نعم* نعم*** لا نعم
tmp/‎ tempDirectory - ق/ك لا** نعم*** لا نعم
  • غ/م => غير متوفر أو غير معروف.
  • * => ملفات تستمر في الذاكرة حتى بعد إعادة تشغيل التطبيق وترقيته، ولكن يمكن أن يمحو نظام التشغيل هذا المجلد في أي وقت. يجب أن يكون تطبيقك قادرًا على إعادة إنشاء أي محتوى مهدد بالحذف.
  • ** => قد تستمر هذه الملفات عبر إعادة تشغيل التطبيق، ولكنّ ذلك ليس أكيدًا. لا يمكن ضمان استمرار هذه الملفات بعد إجراء التحديثات. يجب أن يزيل تطبيقك الملفات من هذا المجلد بنفسه، لأنّه لا توجد ضمانة على أنّ نظام التشغيل سيمحوا هذه الملفات (أو متى يفعل ذلك).
  • *** => قد يمحو نظام التشغيل محتويات هذا المجلد متى رأى أنّ ذلك ضروري، ولكن لا تعتمد على هذا السلوك. يجب عليك مسح هذا المجلد بما يتناسب مع تطبيقك.

بنية نظام الملفات في أندرويد

مسار الجهاز cordova.file.*‎ AndroidExtraFileSystems قراءة/كتابة؟ مستمرة؟ أيمحوه نظام التشغيل؟ خاص
file:///android_asset/‎ applicationDirectory assets ق غ/م غ/م نعم
/data/data/<app-id>/‎ applicationStorageDirectory - ق/ك غ/م غ/م نعم
cache cacheDirectory cache ق/ك نعم نعم* نعم
files dataDirectory files ق/ك نعم لا نعم
Documents - documents ق/ك نعم لا نعم
<sdcard>/‎ externalRootDirectory sdcard ق/ك نعم لا لا
Android/data/<app-id>/‎ externalApplicationStorageDirectory - ق/ك نعم لا لا
cache externalCacheDirectory cache-external ق/ك نعم لا** لا
files externalDataDirectory files-external ق/ك نعم* لا لا
  • غ/م => غير متوفر أو غير معروف.
  • * => قد يمحو نظام التشغيل هذا المجلد بشكل دوري، ولكن لا تعتمد على هذا السلوك. امسح محتويات هذا المجلد بالشكل المناسب لتطبيقك. في حالة قيام المستخدم بمسح ذاكرة التخزين المؤقت يدويًا، ستزال محتويات هذا المجلد.
  • ** => لا يمحو نظام التشغيل هذا المجلد تلقائيًا؛ فأنت المسؤول عن إدارة محتوياته بنفسك. عندما يمحو المستخدم ذاكرة التخزين المؤقت يدويا، ستزال محتويات هذا المجلد.

ملاحظة: إذا تعذر وصل وحدة التخزين الخارجية، ستساوي الخاصيات cordova.file.external*‎ القيمة null.

بنية نظام ملفات منصة OS X

مسار الجهاز cordova.file.*‎ iosExtraFileSystems قراءة/كتابة؟ أيمحوه نظام التشغيل؟ خاص
/Applications/<appname>.app/‎ - bundle ق غ/م نعم
Content/Resources/‎ applicationDirectory - ق غ/م نعم
~/Library/Application Support/<bundle-id>/‎ applicationStorageDirectory - ق/ك لا نعم
files/‎ dataDirectory - ق/ك لا نعم
~/Documents/‎ documentsDirectory documents ق/ك لا لا
~/Library/Caches/<bundle-id>/‎ cacheDirectory cache ق/ك لا نعم
/tmp/ tempDirectory - ق/ك نعم* نعم
/ rootDirectory root ق/ك لا** لا

ملاحظة: هذه هي البنية الخاصة بالتطبيقات غير التجريبية (non sandboxed applications). إذا قمت باستعمال البيئة التجريبية (sandboxing) للتطبيق، فسيصبح الملف applicationStorageDirectory داخل المجلد ‎~/Library/Containers/<bundle-id>/Data/Library/Application Support.

  • * => ملفات تستمر بعد إعادة تشغيل التطبيق أو ترقيته، ولكن يمكن أن يمحو نظام التشغيل هذا المجلد في أي وقت. يجب أن يكون تطبيقك قادرًا على إعادة إنشاء أي محتوى قد يتم حذفه. يجب عليك مسح هذا المجلد بنفسك بما يلائم تطبيقك.
  • ** => يتيح الوصول إلى نظام الملفات بأكمله. وهذا غير متوفر إلا للتطبيقات غير المحصنة.

بنية نظام ملفات ويندوز

مسار الجهاز cordova.file.*‎ قراءة/كتابة؟ أمستمر؟ أيمحوه نظام التشغيل؟ خاص
ms-appdata:///‎ applicationDirectory ق غ/م غ/م نعم
local/‎ dataDirectory ق/ك غ/م لا نعم
temp/‎ cacheDirectory ق/ك لا نعم* نعم
temp/‎ tempDirectory ق/ك لا نعم* نعم
roaming/‎ syncedDataDirectory ق/ك لا لا نعم
  • * => قد يمحو نظام التشغيل هذا المجلد دوريًا.

ملاحظات خاصة بمنصة أندرويد

موضع التخزين الدائم في أندرويد (Android Persistent storage location)

هناك عدة مواضع صالحة لتخزين الملفات بشكل دائم على أجهزة أندرويد . راجع هذه الصفحة لمعلومات مفصلة بخصوص مختلف إمكانيات التخزين المتاحة.

كانت الإصدارات السابقة من هذه الإضافة تختار موضع الملفات المؤقتة والمستمرة (persistent) عند بدء التشغيل، بحسب ما إذا تم وصل (mounted) بطاقة الذاكرة SD (أو أي أداة تخزين مكافئة) على الجهاز أم لا. إن وُصلَت البطاقة SD، أو إن توفرت مساحة تخزين داخلية (على أجهزة Nexus مثلاً)، فستُخزّن الملفات المستمرة في المجلد الجذري لتلك المساحة. هذا يعني أن جميع تطبيقات كورودوفا ستكون قادرة على رؤية جميع الملفات المتوفرة على البطاقة.

في الإصدارات السابقة، إذا لم تكن بطاقة الذاكرة SD متوفرة، فستُخزّن البيانات ضمن المجلد ‎/data/data/<packageId>‎، والذي يعزل التطبيقات عن بعضها البعض، ولكن قد يسمح بتشارك البيانات بين المستخدمين.

من الممكن الآن الاختيار بين تخزين الملفات في وحدة التخزين الداخلية (internal storage)، أو استخدام المقاربة السابقة، يمكنك فعل هذا عبر الوسم preference في الملف config.xml. عبر إضافة أحد هذين السطرين إليه:

<preference name="AndroidPersistentFileLocation" value="Internal" />
<preference name="AndroidPersistentFileLocation" value="Compatibility" />

بدون هذا السطر، ستستخدم إضافة الملفات القيمة Internal كإعداد افتراضي. وفي حال كان الوسم preference حاضرًا، ولم يٌعطى إحدى هاتين القيمتين، فلن يعمل التطبيق.

إذا سبق وأرسلت تطبيقك إلى المستخدمين باستخدام إصدار قديم (قبل الإصدار 3.0.0) من هذه الإضافة، وكان التطبيق قد خزّن الملفات في نظام الملفات الدائمة (persistent filesystem)، فيجب إعطاء الوسم preference القيمة Compatibility إذا لم يحدد الملف config.xml موضع نظام الملفات الدائمة.

قد يؤدي تبديل موضع التخزين وجعله "داخليًّا" (Internal) إلى عدم استطاعة المستخدمين الحاليين الذين يقومون بترقية تطبيقاتهم الوصولَ إلى ملفاتهم المخزنة مسبقًا، وذلك اعتمادًا على الجهاز المستخدم.

إذا كان تطبيقك جديدًا، أو لم يسبق له تخزين الملفات في نظام الملفات الدائمة، فيفضل عمومًا استخدام الإعداد Internal.

العمليات العودية البطيئة على المجلد ‎/android_asset

العمل على مجلدات الأصول (asset directories) بطيئ جدًا في أندرويد. يمكنك تسريع ذلك عن طريق إضافة src/android/build-extras.gradle إلى جذر مشروع أندرويد (يتطلب الإصدار cordova-android@4.0.0 أو ما بعده).

إذن الكتابة على وحدة تخزين خارجية غير موصولة في الإصدار Marshmallow

يتطلب الإصدار Marshmallow أن تستأذن التطبيقات قبل القراءة أو الكتابة في المواضع الخارجية. افتراضيًا، يملك تطبيقك الإذن في الكتابة في cordova.file.applicationStorageDirectory و cordova.file.externalApplicationStorageDirectory، ولن يكون على الإضافة الاستئذان للكتابة في هذين المجلدين إلا إذا لم توصل (mounte) وحدة تخزين خارجية. وفي هذه الحالة، فستطلب الإضافة الإذن للكتابة في cordova.file.externalApplicationStorageDirectory.

ملاحظات خاصة بمنصة iOS

  • cordova.file.applicationStorageDirectory للقراءة فقط؛ ستفشل أي محاولة لتخزين الملفات داخل المجلد الجذري. استخدم أحد الخاصيات cordova.file.*‎ الأخرى المحددة لأجل منصة iOS (فقط المجلدان applicationDirectory و applicationStorageDirectory للقراءة فقط).
  • FileReader.readAsText(blob, encoding)‎
    • المعامل encoding غير مدعوم، والترميز UTF-8 هو المعتمد دائمًا.

موضع التخزين الدائم في منصة iOS

هناك موضعان يصلحان لتخزين الملفات الدائمة على جهاز iOS: مجلد المستندات (Documents directory) ومجلد المكتبة (Library directory). الإصدارات السابقة من الإضافة كانت تخزّن الملفات الدائمة حصرًا في مجلد المستندات. وهذا جعل جميع ملفات التطبيق مرئية في تطبيق iTunes، وهو أمرٌ لم يكن مرغوبًا غالبًا، خاصة للتطبيقات التي تتعامل مع الكثير من الملفات الصغيرة، بدلًا من إنتاج مستندات كاملة لتصديرها، وهو الغرض المقصود من المجلد.

من الممكن الآن اختيار تخزين الملفات في مجلد المستندات أو مجلد المكتبة، عبر الوسم preference في الملف config.xml. وذلك عبر إضافة أحد هذين السطرين إلى config.xml:

<preference name="iosPersistentFileLocation" value="Library" />
<preference name="iosPersistentFileLocation" value="Compatibility" />

بدون هذا السطر، ستستخدم الإضافةُ القيمةَ Compatibility كإعداد افتراضي. في حال كان الوسم preference حاضرًا، ولم يُعطى إحدى هاتين القيمتين، فلن يعمل التطبيق.

إن سبق وأرسلت تطبيقك إلى المستخدمين باستخدام إصدار قديم (قبل الإصدار 1.0) من هذه الإضافة، وكنت قد خزّنت الملفات في نظام الملفات الدائمة، فعليك إعطاء الوسم preference القيمة Compatibility. تحويل الموضع إلى المكتبة (Library) يعني أن المستخدمين الحاليين الذين يقومون بترقية تطبيقاتهم لن يتمكنوا من الوصول إلى ملفاتهم المخزنة مسبقًا.

إن كان تطبيقك جديدًا، أو لم يسبق له تخزين الملفات في نظام الملفات الدائمة، فيفضل عمومًا استخدام الإعداد Library.

ملاحظات خاصة بالمتصفحات (Browsers)

ملاحظات خاصة وتوضيحات

  • يستخدم كل متصفح نظام ملفات محصّن (sandboxed) خاص به. يستخدم المتصفحان IE و فايرفوكس الواجهة البرمجية IndexedDB. كما تستخدم جميع المتصفحات خط مائل ("/") كفاصلة داخل المسار.
  • يجب إنشاء مدخلات المجلد بالتتابع. على سبيل المثال، سيفشل استدعاء التابع fs.root.getDirectory('dir1/dir2', {create:true}, successCallback, errorCallback)‎ إذا لم يكن المجلد dir1 موجودًا.
  • تستأذن الإضافة من المستخدم لاستخدام التخزين الدائم عند بدء التطبيق لأول مرة.
  • تدعم الإضافة cdvfile://localhost (الموارد المحلية) فقط. أي أنّ البروتوكول cdvfile لا يدعم الموارد الخارجية.
  • لا تتقيّد الإضافة "بتسميات الواجهة البرمجية لنظام الملفات 8.3".
  • الكائن Blob و التابع‏ close غير مدعومان.
  • لا تدعم هذه الإضافة FileSaver و BlobBuilder، وليس لهما جذوع (stubs).
  • الإضافة لا تدعم الدالة requestAllFileSystems. هذه الدالة غير موجودة في المواصفات أيضًا.
  • لن تُزال المُدخلات (Entries) من المجلد إن كنت تستخدم الراية create: true مع مجلد موجود.
  • الملفات المُنشأة عبر الباني (constructor) ليست مدعومة. عليك استخدام التابع entry.file بدلًا من ذلك.
  • يستخدم كل متصفح شكلًا خاصًا من عناوين blob.
  • الدالة readAsDataURL مدعومة، لكنّ نوع الوسيط mediatype في متصفح كروم يعتمد على امتداد اسم المُدخلات (entry name extension)؛ نوع الوسيط mediatype في المتصفح IE يكون دائمًا فارغًا (وهو أمر مماثل لـ text-plain وفقًا للمواصفات)، أما في متصفح فايرفوكس، فإنّ نوع الوسيط mediatype يساوي دائمًا application/octet-stream. على سبيل المثال، إن كان المحتوى هو abcdefg، فحينئذٍ سيعيد فايرفوكس القيمة data:application/octet-stream;base64,YWJjZGVmZw==‎، وسيعيد المتصفح IE القيمة data:;base64,YWJjZGVmZw==‎، فيما سيعيد المتصفح كروم القيمة data:<mediatype depending on extension of entry name>;base64,YWJjZGVmZw==‎.
  • تُعيد الخاصية toInternalURL المسار وفق الصيغة file:///persistent/path/to/entry (على فايرفوكس و IE). فيما يعيد كروم المسار وفق الصيغة cdvfile://localhost/persistent/file.

ملاحظات خاصة بمتصفح كروم

  • نظام الملفات في متصفح كروم لا يكون جاهزًا أثناء إطلاق الحدث deviceready؛ لتجاوز هذه المشكلة، يمكنك الاشتراك في الحدث filePluginIsReady. على سبيل مثال:
window.addEventListener('filePluginIsReady', function(){ console.log('File plugin is ready');}, false);

يمكنك استخدام الدالة window.isFilePluginReadyRaised للتحقق مما إذا كان الحدث قد أُطلِق بالفعل.

  • حصة نظام الملفات window.requestFileSystem المؤقت (TEMPORARY) أو الدائم (PERSISTENT) غير محدودة في متصفح كروم.
  • لزيادة سعة التخزين الدائم (persistent storage) في كروم، يلزمك استدعاء التابع window.initPersistentFileSystem. افتراضيًا، تبلغ حصة التخزين الدائم 5 ميغابايت.
  • يتطلب كروم تمرير الوسيط ‎--allow-file-access-from-files إلى الأمر run لدعم الواجهة البرمجية (API) عبر البروتوكول file:///‎.
  • لن يُغيّر الكائن File إن كنت تستخدم الراية {create:true} عند الحصول على مدخل Entry موجود.
  • تُضبط خاصية الأحداث cancelable عند القيمة true في متصفح كروم. على خلاف ما تقوله المواصفات.
  • تعيد الدالة toURL في كروم مسارًا مسبوقًا بالبادئة filesystem:‎ بناءً على التطبيق المُضيف. مثلًا:
    • filesystem:file:///persistent/somefile.txt
    • filesystem:http://localhost:8080/persistent/somefile.txt.
  • لا تحتوي نتيجة الدالة toURL على خط مائل في حالة directoryEntry. مع ذلك، يستبين كروم المجلدات ذات العناوين url التي تنتهي بخط مائل بشكلٍ صحيح.
  • يتطلب التابع resolveLocalFileSystemURL أن يبدأ العنوان الخلفي بالبادئة filesystem. على سبيل المثال، يجب أن يكون المعامل url الخاص بالتابع resolveLocalFileSystemURL مكتوبًا وفق الصيغة filesystem:file:///persistent/somefile.txt بدلًا من الصيغة file:///persistent/somefile.txt المعمول بها في أندرويد.
  • الدالة toNativeURL ليست مدعومة، وليس لها جذع (stub).
  • الدالة setMetadata ليست مذكورة في المواصفات وليست مدعومة.
  • يُطلق الخطأ INVALIDMODIFICATIONERR (ذو الرمز 9) بدلًا من الخطأ SYNTAX_ERR (ذي الرمز 8) عند طلب (requesting) نظام ملفات غير موجود.
  • يُطلق الخطأ INVALIDMODIFICATIONERR (ذو الرمز 9) بدلًا من الخطأ PATHEXISTSERR (ذي الرمز 12) عند محاولة إنشاء ملف أو مجلد موجود مسبقًا.
  • يُطلق الخطأ INVALIDMODIFICATIONERR (ذو الرمز 9) بدلًا من الخطأ NOMODIFICATIONALLOWED_ERR (ذي الرمز 6) عند محاولة استدعاء removeRecursively على المجلد الجذري (root) لنظام الملفات.
  • يُطلق الخطأ INVALIDMODIFICATIONERR (ذو الرمز 9) بدلًا من الخطأ NOTFOUNDERR (ذي الرمز 1) عند محاولة الانتقال إلى مجلد غير موجود.

ملاحظات خاصة بالمنصات التي تستخدم IndexedDB (فايرفوكس و IE)

  • الصيغتان . و .. غير مدعومتان.
  • لا يدعم المتصفح IE العناوينfile:///‎؛ ولكن يدعم الوضع المستضاف فقط (http://localhost:xxxx).
  • حجم نظام الملفات في فايرفوكس غير محدود، ولكن عند كل تمديد للمساحة إلى 50 ميغابايت، فسيُطلب إذن المستخدم. يتيح المتصفح IE10 إلى حدود 10 ميغابايت من الذاكرتين AppCache و IndexedDB المُستخدمتين في نظام الملفات دون المطالبة بإذن، وبمجرد أن تصل إلى هذا المستوى، سيُطلب منك الإذن لزيادة هذا الحجم إلى 250 ميغابايت كحد أقصى لكل موقع. لذلك، لا يؤثر المعامل size الخاص بالدالة requestFileSystem على نظام الملفات في المتصفحين فايرفوكس و IE.
  • الدالة readAsBinaryString لم تُذكر في المواصفات، وليست مدعومة في المتصفح IE، وليس لها جذع (stub).
  • الخاصية file.type تساوي دائما null.
  • عليك ألا تنشئ مُدخلات (entries) باستخدام نتيجة دالة الاستجابة (callback) الخاصة بنسخة DirectoryEntry المحذوفة. وإلا فستحصل على مُدخلة مُعلّقة (hanging entry).
  • قبل أن تتمكن من قراءة ملف مكتوب للتّو، عليك أن تحصل أولًا على نسخة جديدة من ذلك الملف.
  • الدالة setMetadata، والتي لم تُذكر في المواصفات، تدعم تغيير الحقل modificationTime فقط.
  • لا تدعم الدالتان copyTo و moveTo المجلدات.
  • البيانات الوصفية (metadata) للمجلدات غير مدعومة.
  • لا يفشل التابعان Entry.remove و directoryEntry.removeRecursively عند إزالة المجلدات غير الفارغة، إذ يمحوان المجلدات المُزالة مع محتوياتها.
  • الدالتان abort و truncate غير مدعومتان.
  • لا يتم إطلاق أحداث التقدم (progress events). على سبيل المثال، لن يُنفّذ معالج الحدث التالي: javascript writer.onprogress = function() { /*commands*/ };‎.

ملاحظات حول الترقية

في الإصدار 1.0.0 من هذه الإضافة، تغيرت بِنيتَا الكائنين FileEntry و DirectoryEntry لتصبحا أكثر انسجامًا مع المواصفات المنشورة.

الإصدارات السابقة (قبل 1.0.0) من الإضافة كانت تُخزن device-absolute-file-location في الخاصية fullPath في الكائن Entry. هذه المسارات تبدو عادةً كالتالي:

/var/mobile/Applications/<application UUID>/Documents/path/to/file  (iOS)
/storage/emulated/0/path/to/file                                    (Android)‎

تُعاد هذه المسارات أيضًا من قبل التابع toURL()‎ الخاص بالكائن Entry.

في الإصدار 1.0.0، أصبحت الخاصية fullPath تمثل مسار الملف نسبةً إلى المجلد الجذري لنظام ملفات HTML. لذلك، فالمسارات المذكورة أعلاه سيمثّلها الآن الكائن FileEntry كمسار كامل (الخاصية fullPath) على النحو التالي:

/path/to/file‎

إن كان تطبيقك يعمل مع device-absolute-paths، وقمت سابقًا باسترداد هذه المسارات عبر الخاصية fullPath من كائنات Entry، فعليك تحديث شيفرتك البرمجية لاستخدام entry.toURL()‎ بدلًا من ذلك.

للتوافق مع الإصدارات القديمة، سيقبل التابع resolveLocalFileSystemURL()‎ المعامل device-absolute-path، وسيُعيد كائن Entry مقابلًا له، طالما أنّ الملف موجود داخل أحد نظامي الملفات المؤقتة (TEMPORARY) أو المستمرة (PERSISTENT).

كانت هذه مشكلة خاصة بالإضافة File-Transfer، إذ كانت تستخدم سابقًا مسارات مطلقة للجهاز device-absolute-paths (ولا تزال تقبلها). وقد تم تحديثها لتعمل بشكل صحيح مع روابط نظام الملفات (FileSystem URLs)، لذلك، فاستبدال entry.fullPath بالتابع entry.toURL()‎ سيحل أية مشاكل قد تواجه الإضافة عند العمل على الملفات الموجودة على الجهاز.

في الإصدار 1.1.0، تم تغيير القيمة المعادة من الدالة toURL()‎ (انظر الصفحة CB-6394)، إذ باتت تعيد الرابط المطلق "file://‎" ما أمكن. للحصول على رابط داخلي ‎'cdvfile:'‎، يمكنك استخدام التابع toInternalURL()‎. والذي أصبح يعيد عناوين نظام الملفات وفق الصيغة التالية:

cdvfile://localhost/persistent/path/to/file‎

يمكن استخدام هذه العناوين لتحديد الملف بدقة.

البروتوكول cdvfile

يمكن استخدام cdvfile://localhost/persistent|temporary|another-fs-root*/path/to/file في مسارات الملفات المستقلة عن المنصة (platform-independent). المسارات cdvfile مدعومة من قبل الإضافات الأساسية (core plugins)؛ فعلى سبيل المثال، يمكنك تنزيل ملف mp3 إلى مسار cdvfile عبر الإضافة cordova-plugin-file-transfer ثم تشغيله عبر الإضافة cordova-plugin-media.

ملاحظة: راجع الفقرات مكان تخزين الملفات وبنيات نظام الملفات وتعديل إعددات الإضافة لمزيد من التفاصيل حول جذور نظام الملفات المتاحة.

لاستخدام cdvfile كخاصية وَسْمِية src، يمكنك تحويلها إلى مسار أصلي عبر التابع toURL()‎ الخاص بالكائن fileEntry الناتج، والذي يمكنك الحصول عليه عبر resolveLocalFileSystemURL؛ راجع الأمثلة أدناه.

يمكنك أيضًا استخدام المسارات cdvfile://‎ مباشرةً داخل DOM مثل:

<img src="cdvfile://localhost/persistent/img/logo.png" />

ملاحظة: يتطلب هذا التابع تحديثات الأمان التالية:

  • أضف cdvfile:‎ إلى الوسم الوصفي Content-Security-Policy في صفحة الفهرس، على سبيل المثال:
<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap:cdvfile:https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
  • أضف <access origin="cdvfile://*" /‎> إلى الملف config.xml.

مثال عن تحويل cdvfile:// إلى مسار أصلي:

resolveLocalFileSystemURL('cdvfile://localhost/temporary/path/to/file.mp4', function(entry) {
    var nativePath = entry.toURL();
    console.log('Native URI: ' + nativePath);
    document.getElementById('video').src = nativePath;

مثال عن تحويل مسار أصلي إلى cdvfile://:

resolveLocalFileSystemURL(nativePath, function(entry) {
    console.log('cdvfile URI: ' + entry.toInternalURL());

مثال حول استخدام cdvfile:// في الإضافات الأساسية:

fileTransfer.download(uri, 'cdvfile://localhost/temporary/path/to/file.mp3', function (entry) { ...
var my_media = new Media('cdvfile://localhost/temporary/path/to/file.mp3', ...);
my_media.play();

ملاحظات خاصة بالبروتوكول cdvfile

  • استخدام المسارات cdvfile://‎ في DOM غير مدعوم في منصة ويندوز (يمكن تحويل المسار إلى مسار أصلي لتجاوز ذلك).

لائحة رموز الأخطاء ومعانيها

عند إطلاق خطأ، سيتم استخدام أحد الرموز التالية:

كود الخطأ الثابتة
1 NOT_FOUND_ERR
2 SECURITY_ERR
3 ABORT_ERR
4 NOT_READABLE_ERR
5 ENCODING_ERR
6 NO_MODIFICATION_ALLOWED_ERR
7 INVALID_STATE_ERR
8 SYNTAX_ERR
9 INVALID_MODIFICATION_ERR
10 QUOTA_EXCEEDED_ERR
11 TYPE_MISMATCH_ERR
12 PATH_EXISTS_ERR

تعديل إعدادات الإضافة (اختياري)

يمكن تعديل إعدادات أنظمة الملفات المتاحة لكل منصة على حدة. تتعرف المنصتان iOS و أندرويد على وسمٍ في الملف config.xml، والذي يحتوي أسماء أنظمة الملفات المراد تثبيتها. بشكل افتراضي، يتم تمكين كل جذور (roots) نظام الملفات.

<preference name="iosExtraFilesystems" value="library,library-nosync,documents,documents-nosync,cache,bundle,root" />
<preference name="AndroidExtraFilesystems" value="files,files-external,documents,sdcard,cache,cache-external,assets,root" />

منصة أندرويد

  • files: مجلد التخزين الداخلي للملفات.
  • files-external: مجلد التخزين الخارجي للملفات.
  • sdcard: مجلد التخزين الخارجي العام للملفات (global external file storage) الذي يساوي جذر بطاقة الذاكرة SD، إن كانت موصولة. يجب أن يكون لديك الإذن android.permission.WRITE_EXTERNAL_STORAGE لاستخدامه.
  • cache: مجلد التخزين المؤقت الداخلي للتطبيق.
  • cache-external: مجلد التخزين المؤقت الخارجي للتطبيق.
  • assets: حزمة (bundle) التطبيق (للقراءة فقط).
  • root: نظام ملفات الجهاز بأكمله.
  • applicationDirectory: للقراءة فقط مع وصول مقيد. يمكن نسخ الملفات في هذا المجلد، ولكن في حال محاولة قرائتها مباشرة سينتج عن ذلك تنبيه "file not found". يدعم أندرويد أيضًا نظام ملفات خاص باسم "documents"، والذي يمثل مجلدًا فرعيًا "/Documents/" داخل نظام الملفات "files".

منصة iOS

  • library: مجلد مكتبة التطبيق.
  • documents: مجلد مستندات (Documents) التطبيق.
  • cache: مجلد ذاكرة التخزين المؤقت للتطبيق.
  • bundle: حزمة التطبيق، وهو موضع التطبيق نفسه على القرص (للقراءة فقط).
  • root: نظام ملفات الجهاز بأكمله.

افتراضيًا، يمكن مزامنة مجلدي المستندات (documents) والمكتبة (library) مع السحابة iCloud. يمكنك أيضًا طلب (request) نظامي ملفات إضافيين، وهما library-nosync و documents-nosync اللذان يمثلان مجلدًا خاصًا غير متزامن داخل نظام الملفات ‎/Library أو ‎/Documents.

مثال عملي

تتيح لك إضافة الملفات تنفيذ العديد من الأشياء، مثل تخزين الملفات في موقع تخزين مؤقت أو دائم لأجل استخدامه من قبل تطبيقك (تخزين تجريبي [sandboxed storage])، أو تخزين الملفات في مواقع أخرى بحسب المنصة المُستخدمة.

توضح الشيفرات البرمجية في هذا القسم بعض هذه الأمور، مثل:

إنشاء ملف دائم

قبل استخدام الواجهات البرمجية لإضافة الملفات، يمكنك الوصول إلى نظام الملفات باستخدام requestFileSystem. عند القيام بذلك، يمكنك طلب استخدام التخزين الدائم أو المؤقت. وفي حال اخترت التخزين الدائم، فلن يُزال إلا بإذن المستخدم.

عندما تحصل على إذن الوصول إلى نظام الملفات عبر requestFileSystem، يُمنح إذن الوصول لنظام الملفات المقيد في وضع الحماية (sandboxed) فقط (يقيد وضع حجرة الحماية [sandbox] حق الوصول على التطبيق وحده)، ولا يمنح حق الوصول العام إلى أي موضع في نظام الملفات على الجهاز. (للوصول إلى مواضع نظام الملفات الواقعة خارج مساحة التخزين المقيدة له فقط، استخدم توابع أخرى مثل التابع window.resolveLocalFileSystemURL، والذي يدعم المواضع المخصوصة بمنصات معينة. لمثال على ذلك، انظر فقرة "إضافة محتوى إلى ملف".) في هذا المثال تجد طلبًا للتخزين المستمر.

ملاحظة: عند استهداف عملاء العارض WebView (بدلًا من المتصفح)، أو التطبيقات الأصلية (ويندوز)، فلا تحتاج إلى استخدام requestQuota قبل استخدام التخزين الدائم.

window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fs) {

    console.log('file system open: ' + fs.name);
    fs.root.getFile("newPersistentFile.txt", { create: true, exclusive: false }, function (fileEntry) {

        console.log("fileEntry is file?" + fileEntry.isFile.toString());
        // fileEntry.name == 'someFile.txt'
        // fileEntry.fullPath == '/someFile.txt'
        writeFile(fileEntry, null);

    }, onErrorCreateFile);

}, onErrorLoadFs);

تتلقى دالة رد نداء النجاح (success callback) الكائن FileSystem. إن أردت إعادة كائنٍ DirectoryEntry، فاستخدم fs.root، والذي يمكنك استخدامه لإنشاء أو الحصول على ملف (عن طريق استدعاء التابع getFile). يمثل fs.root في هذا المثال كائنًا DirectoryEntry، والذي يمثل التخزين الدائم في نظام الملفات المقيد (sandboxed file system).

تتلقى دالة رد نداء النجاح (success callback) الخاصة بالتابع getFile الكائن FileEntry. الذي يمكنك استخدامه لتنفيذ عمليات الكتابة والقراءة على الملف.

إنشاء ملف مؤقت

في ما يلي مثال لطلب تخزينٍ مؤقت. تذكّر أنه قد يتم حذف التخزين المؤقت من قبل نظام التشغيل في حال انحسار ذاكرة الجهاز.

window.requestFileSystem(window.TEMPORARY, 5 * 1024 * 1024, function (fs) {

    console.log('file system open: ' + fs.name);
    createFile(fs.root, "newTempFile.txt", false);

}, onErrorLoadFs);

عندما تستخدم التخزين المؤقت، يمكنك إنشاء أو الحصول على الملف عن طريق استدعاء التابع getFile. وكما في مثال التخزين المستمر، سيعطيك هذا الكائن FileEntry الذي يمكنك استخدامه في عمليات القراءة أو الكتابة.

function createFile(dirEntry, fileName, isAppend) {
    // انشاء ملف جديد أو إعادة الملف إن كان موجودا سلفا
    dirEntry.getFile(fileName, {create: true, exclusive: false}, function(fileEntry) {
        writeFile(fileEntry, null, isAppend);
    }, onErrorCreateFile);
}

الكتابة في ملف

بمجرد الحصول على الكائن FileEntry، يمكنك الكتابة في الملف عن طريق استدعاء التابع createWriter، والذي يعيد الكائن FileWriter في دالة رد نداء النجاح (success callback).

استدع التابع write الخاص بالكائن FileWriter للكتابة في الملف.

function writeFile(fileEntry, dataObj) {
    // (log.txt) FileEntry لأجل الكائن FileWriter انشاء
    fileEntry.createWriter(function (fileWriter) {
        fileWriter.onwriteend = function() {
            console.log("Successful file write...");
            readFile(fileEntry);
        };
        fileWriter.onerror = function (e) {
            console.log("Failed file write: " + e.toString());
        };
        // dataObj  في حال عدم تمرير كائن البيانات 
        // جديد Blob  أنشئ كائن.
        if (!dataObj) {
            dataObj = new Blob(['some file data'], { type: 'text/plain' });
        }
        fileWriter.write(dataObj);
    });
}

قراءة ملف

تحتاج إلى الكائن FileEntry لقراءة ملف موجود. استخدم الخاصية file في الكائن FileEntry للحصول على مرجع الملف، ثم أنشئ كائنًا جديدًا من النوع FileReader. يمكنك استخدام توابع مثل التابع readAsText لبدء عملية القراءة.

عند اكتمال عملية القراءة، ستخزن الخاصيةُ this.result نتيجةَ عمليةِ القراءة.

function readFile(fileEntry) {
    fileEntry.file(function (file) {
        var reader = new FileReader();
        reader.onloadend = function() {
            console.log("Successful file read: " + this.result);
            displayFileData(fileEntry.fullPath + ": " + this.result);
        };
        reader.readAsText(file);
    }, onErrorReadFile);
}

إضافة محتوى إلى ملف باستخدام طرق بديلة

ستحتاج غالبًا إلى إضافة محتوًى إلى الملفات الموجودة بدلًا من إنشاء ملفات جديدة. إليك مثالًا على ذلك.

يوضح هذا المثال طريقة أخرى يمكنك من خلالها الوصول إلى نظام الملفات باستخدام window.resolveLocalFileSystemURL. في هذا المثال، ستقوم بتمرير عنوان الملف المستقل عن المنصات cordova.file.dataDirectory إلى الدالة. تتلقى دالة رد نداء النجاح (success callback) كائنًا من النوع DirectoryEntry الذي يمكنك استخدامه للقيام بعدة أمور مثل إنشاء ملفٍ وما شابه.

window.resolveLocalFileSystemURL(cordova.file.dataDirectory, function (dirEntry) {
    console.log('file system open: ' + dirEntry.name);
    var isAppend = true;
    createFile(dirEntry, "fileToAppend.txt", isAppend);
}, onErrorLoadFs);

بالإضافة إلى هذا، يمكنك استخدام التابع resolveLocalFileSystemURL للوصول إلى بعض مواضع نظام الملفات التي لا تدخل في نظام التخزين المقيَّد. راجع قسم مكان تخزين الملفات لمزيد من المعلومات؛ العديد من مواضع التخزين هذه مخصوصة بالمنصات. يمكنك أيضًا تمرير مواضع نظام ملفات مستقلة عن المنصات إلى التابع resolveLocalFileSystemURL باستخدام البروتوكول cdvfile.

بالنسبة إلى عملية الإضافة (append)، لا يوجد شيء جديد في الدالة createFile التي استدعيناها في الشيفرة البرمجية السابقة (راجع الأمثلة السابقة لمطالعة الشيفرات الفعلية). حيث تستدعي createFile الدالة writeFile. لكن عليك أن تتحقق من writeFile مما إذا كانت عملية الإضافة مطلوبة أم لا.

بمجرد الحصول على الكائن FileWriter، استدعِ التابع seek، ومرّر إليه فهرس الموضع الذي تريد الكتابة عنده.

في هذا المثال، سنتحقق أيضًا من وجود الملف. وبعد استدعاء التابع seek، سنستدعي التابع write الخاص بالكائن FileWriter.

function writeFile(fileEntry, dataObj, isAppend) {
    // (log.txt) FileEntry لأجل الكائن FileWriter انشاء
    fileEntry.createWriter(function (fileWriter) {
        fileWriter.onwriteend = function() {
            console.log("Successful file read...");
            readFile(fileEntry);
        };
        fileWriter.onerror = function (e) {
            console.log("Failed file read: " + e.toString());
        };
        // في حال إضافة بيانات إلى الملف، اذهب إلى نهاية الملف
        if (isAppend) {
            try {
                fileWriter.seek(fileWriter.length);
            }
            catch (e) {
                console.log("file doesn't exist!");
            }
        }
        fileWriter.write(dataObj);
    });
}

تخزين ملف ثنائي موجود (Store an existing binary file)

سبق ووضحنا كيفية الكتابة في ملف أنشأته للتو في نظام الملفات المقيد. لكن ماذا لو احتجت إلى الوصول إلى ملف موجود، وأردت جعله قابلًا للتخزين على جهازك؟ في هذا المثال، ستحصل على ملف باستخدام طلبية xhr ‏(xhr request‏)، ثم ستحفظه في ذاكرة التخزين المؤقت في نظام الملفات المُحصّنة.

قبل الحصول على الملف، عليك الحصول أولًا على مرجع لكائن FileSystem باستخدام التابع requestFileSystem. مع إعطائه القيمة window.TEMPORARY (كما فعلنا من قبل)، يمثل الكائن FileSystem المعاد ذاكرة التخزين المؤقت في نظام الملفات المقيِّد.

استخدم fs.root للحصول على الكائن DirectoryEntry الذي تحتاجه.

window.requestFileSystem(window.TEMPORARY, 5 * 1024 * 1024, function (fs) {
    console.log('file system open: ' + fs.name);
    getSampleFile(fs.root);
}, onErrorLoadFs);

في الختام، إليك طلبية xhr للحصول على الصورة Blob. لا يوجد أي شيء خاص بكوردوفا في هذه الشيفرة، باستثناء أنك ستقوم بإعادة توجيه مرجع DirectoryEntry الذي حصلت عليه بالفعل إلى الدالة saveFile كوسيط. سوف تقوم بحفظ الصورة وعرضها في وقت لاحق بعد قراءة الملف (للتحقق من صحة العملية).

function getSampleFile(dirEntry) {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'http://cordova.apache.org/static/img/cordova_bot.png', true);
    xhr.responseType = 'blob';
    xhr.onload = function() {
        if (this.status == 200) {
            var blob = new Blob([this.response], { type: 'image/png' });
            saveFile(dirEntry, blob, "downloadedImage.png");
        }
    };
    xhr.send();
}

ملاحظة: كجزء من إجراءات الأمان في كوردوفا 5، تتطلب الشيفرة السابقة إضافة اسم النطاق، http://cordova.apache.org، إلى العنصر Content-Security-Policy في الملف index.html.

بعد الحصول على الملف، انسخ المحتويات في ملف جديد. الكائن DirectoryEntry الحالي مرتبط بالفعل مع المخزن المؤقت (cache) للتطبيق.

function saveFile(dirEntry, fileData, fileName) {
    dirEntry.getFile(fileName, { create: true, exclusive: false }, function (fileEntry) {
        writeFile(fileEntry, fileData);
    }, onErrorCreateFile);
}

ستمرر كائن الملف Blob إلى الدالة writeFile باعتباره كائن البيانات dataObj، وستحفظه في الملف الجديد.

function writeFile(fileEntry, dataObj, isAppend) {
    // (log.txt) FileEntry لأجل الكائن FileWriter انشاء
    fileEntry.createWriter(function (fileWriter) {
        fileWriter.onwriteend = function() {
            console.log("Successful file write...");
            if (dataObj.type == "image/png") {
                readBinaryFile(fileEntry);
            }
            else {
                readFile(fileEntry);
            }
        };
        fileWriter.onerror = function(e) {
            console.log("Failed file write: " + e.toString());
        };
        fileWriter.write(dataObj);
    });
}

بعد الكتابة في الملف، اقرأه وقم بعرضه. وبما أنّك حفظت الصورة على هيئة بيانات ثنائية (binary data)، فيمكنك قراءتها باستخدام التابع FileReader.readAsArrayBuffer.

function readBinaryFile(fileEntry) {
    fileEntry.file(function (file) {
        var reader = new FileReader();
        reader.onloadend = function() {
            console.log("Successful file write: " + this.result);
            displayFileData(fileEntry.fullPath + ": " + this.result);
            var blob = new Blob([new Uint8Array(this.result)], { type: "image/png" });
            displayImage(blob);
        };
        reader.readAsArrayBuffer(file);
    }, onErrorReadFile);
}

بعد قراءة البيانات، يمكنك عرض الصورة باستخدام الشيفرة الموضحة في المثال التالي. استخدم window.URL.createObjectURL للحصول على السلسلة النصية DOM الخاصة بالصورة Blob.

function displayImage(blob) {
    // استخدم الصورة إن كانت النتيجة عبارة عن 
    // DOM سلسلة نصية تمثل صورة صالحة في
    var elem = document.getElementById('imageFile');
    // عند إنهاء الصورة window.URL.revokeObjectURL ملاحظة:استخدم
    elem.src = window.URL.createObjectURL(blob);
}

عرض ملف صورة

لعرض صورة باستخدام FileEntry، يمكنك استدعاء التابع toURL بالشكل التالي:

function displayImageByFileURL(fileEntry) {
    var elem = document.getElementById('imageFile');
    elem.src = fileEntry.toURL();
}

إن كنت تستخدم عناوين مخصوصة بمنصات معينة بدلًا من FileEntry، وأردت عرض صورة، فقد تحتاج إلى تضمين الجزء الرئيسي من العنوان في العنصر Content-Security-Policy في الملف index.html.

على سبيل المثال، في ويندوز 10، يمكنك تضمين ms-appdata:‎ في ذلك العنصر. كما يوضح المثال التالي:

<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: ms-appdata: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">

إنشاء المجلدات

في الشيفرة التالية، ستنشئ مجلدات في المجلد الجذري للمخزن (root storage location) الخاص بالتطبيق. يمكنك استخدام هذه الشيفرة مع أي موضع تخزين قابل للكتابة (DirectoryEntry). في هذا المثال، ستكتب في ذاكرة التخزين المؤقت للتطبيق (على افتراض أنك حصلت على الكائن FileSystem عبر window.TEMPORARY ) عن طريق تمرير fs.root إلى هذه الدالة.

تنشئ هذه الشيفرة المجلد ‎/NewDirInRoot/images‎ في المخزن المؤقت للتطبيق (بخصوص القيم المخصوصة بمنصات معينة، راجع فقرة تخطيط نظام الملفات أعلاه).

function createDirectory(rootDirEntry) {
    rootDirEntry.getDirectory('NewDirInRoot', { create: true }, function (dirEntry) {
        dirEntry.getDirectory('images', { create: true }, function (subDirEntry) {
            createFile(subDirEntry, "fileInNewSubDir.txt");
        }, onErrorGetDir);
    }, onErrorGetDir);
}

عند إنشاء مجلدات فرعية، عليك إنشاء كل مجلد على حدة كما هو موضح في الشيفرة البرمجية السابقة.

انظر أيضًا

مصادر