مراقبة الملفات - كيفية معرفة وقت اكتمال الملف

StackOverflow https://stackoverflow.com/questions/30074

  •  09-06-2019
  •  | 
  •  

سؤال

لدينا العديد من تطبيقات .NET التي تراقب دليلاً للملفات الجديدة باستخدام FileSystemWatcher.يتم نسخ الملفات من موقع آخر، وتحميلها عبر FTP، وما إلى ذلك.عند وصولهم، تتم معالجة الملفات بطريقة أو بأخرى.ومع ذلك، هناك مشكلة واحدة لم أجد لها إجابة مرضية أبدًا وهي:بالنسبة للملفات الكبيرة، كيف يمكن معرفة ما إذا كانت الملفات التي تتم مراقبتها لا تزال قيد الكتابة؟من الواضح أننا بحاجة إلى الانتظار حتى اكتمال الملفات وإغلاقها قبل أن نبدأ في معالجتها.لا يبدو أن وسيطات الحدث في أحداث FileSystemWatcher تعالج هذه المشكلة.

هل كانت مفيدة؟

المحلول

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

نصائح أخرى

إذا كنت تتحكم في البرنامج الذي يقوم بكتابة الملفات في الدليل، فيمكنك جعل البرنامج يكتب الملفات إلى دليل مؤقت ثم ينقلها إلى الدليل المراقب.يجب أن تكون عملية النقل عملية ذرية، لذلك لا ينبغي للمراقب رؤية الملف حتى يتم وضعه بالكامل في الدليل.

إذا لم تكن متحكمًا في ما تتم كتابته في الدليل المُراقب، فيمكنك ضبط وقت في المراقب حيث يعتبر الملف مكتملًا عندما يظل بنفس الحجم في الوقت المحدد.إذا لم تكن المعالجة الفورية مصدر قلق، فإن ضبط هذا المؤقت على شيء كبير نسبيًا يعد طريقة آمنة إلى حد ما لمعرفة ما إذا كان الملف مكتملًا أو أنه لن يكتمل أبدًا.

يجب ألا يتم إطلاق الحدث "Changed" الموجود على FileSystemWatcher حتى يتم إغلاق الملف.انظر بلدي الإجابة على سؤال مماثل.هناك احتمال أن تقوم آلية تنزيل FTP بإغلاق الملف عدة مرات أثناء التنزيل عند وصول بيانات جديدة، لكنني أعتقد أن هذا غير مرجح إلى حد ما.

ما لم يكن من الممكن التحقق من اكتمال محتويات الملف (يحتوي على تنسيق يمكن التحقق منه أو يتضمن مجموعًا اختباريًا للمحتويات) يمكن للمرسل فقط التحقق من وصول الملف بأكمله.

لقد استخدمت طريقة قفل لإرسال الملفات الكبيرة عبر FTP في الماضي.

يتم إرسال الملف بامتداد بديل وتتم إعادة تسميته بمجرد أن يكون المرسل سعيدًا بوجود كل شيء هناك.

من الواضح أنه يتم دمج ما ورد أعلاه مع عملية تقوم بشكل دوري بترتيب الملفات القديمة بالملحق المؤقت.

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

بدون نظام مثل هذا، لا يمكن للمتلقي التأكد من وصول الملف بأكمله.

يعد التحقق من الملفات التي لم يتم تغييرها خلال x دقيقة عرضة لجميع أنواع المشكلات.

تحاول الطريقة التالية فتح ملف بأذونات الكتابة.سيمنع التنفيذ حتى تتم كتابة الملف بالكامل على القرص:

/// <summary>
/// Waits until a file can be opened with write permission
/// </summary>
public static void WaitReady(string fileName)
{
    while (true)
    {
        try
        {
            using (System.IO.Stream stream = System.IO.File.Open(fileName, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
            {
                if (stream != null)
                {
                    System.Diagnostics.Trace.WriteLine(string.Format("Output file {0} ready.", fileName));
                    break;
                }
            }
        }
        catch (FileNotFoundException ex)
        {
            System.Diagnostics.Trace.WriteLine(string.Format("Output file {0} not yet ready ({1})", fileName, ex.Message));
        }
        catch (IOException ex)
        {
            System.Diagnostics.Trace.WriteLine(string.Format("Output file {0} not yet ready ({1})", fileName, ex.Message));
        }
        catch (UnauthorizedAccessException ex)
        {
            System.Diagnostics.Trace.WriteLine(string.Format("Output file {0} not yet ready ({1})", fileName, ex.Message));
        }
        Thread.Sleep(500);
    }
}

(من إجابتي إلى أ سؤال ذو صلة)

ربما يتعين عليك استخدام بعض الإشارات خارج النطاق:اطلب من منتج "file.ext" كتابة "file.ext.end" الوهمي.

+1 لاستخدام إشارة file.ext.end إن أمكن، حيث تكون محتويات file.ext.end عبارة عن مجموع اختباري للملف الأكبر.هذا ليس من أجل الأمان بقدر ما هو للتأكد من عدم حدوث أي تشويش على طول الطريق.إذا تمكن شخص ما من إدراج ملف خاص به في الدفق الكبير، فيمكنه استبدال المجموع الاختباري أيضًا.

لا يساعد قفل الكتابة إذا فشل تحميل الملف جزئيًا ولم يحاول المرسل إعادة إرسال (وإعادة قفل) الملف حتى الآن.

الطريقة التي أتحقق بها في Windows مما إذا كان الملف قد تم تحميله بالكامل بواسطة بروتوكول نقل الملفات هو محاولة إعادة تسميته.إذا فشلت إعادة التسمية، فهذا يعني أن الملف غير مكتمل.أعترف أنه ليس أنيقًا جدًا، لكنه يعمل.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top