برنامه نویسی

هنگام بارگیری آن در یک فایل ZIP ، تاریخ ایجاد و پردازش پرونده را حفظ کنید

به عنوان بخشی از یک پروژه فعلی ، لازم بود که هنگام بارگیری پرونده ها از مرورگر ، تاریخ ایجاد و تاریخ پردازش حفظ شود. رفتار استاندارد مرورگرها این است که هر دو را در زمان فعلی بارگیری کنید (برخی از تحقیقات نشان داده است که این رفتار را نمی توان در مرورگر هنگام بارگیری انجام داد).

به عنوان مثال ، در اینجا تصویر جلد: فقط بارگیری شده است ، اما مطمئناً دقیقاً ایجاد نشده است.
ابرداده استاندارد

راه حل این بود که همیشه پرونده ها را در پرونده های ZIP بارگیری کرده و تاریخ ایجاد و پردازش را در آنجا تطبیق دهیم. متأسفانه ، در .NET و کتابخانه های مشترک همیشه فقط همین است آخرین مدافع برای تغییر موجود است. ظاهراً استاندارد فقط از این مقدار پشتیبانی می کند.

خوشبختانه ، تعریف ZIP از یک قسمت NTFS-Extra پشتیبانی می کند:

   4.5.5 -NTFS Extra Field (0x000a):

      The following is the layout of the NTFS attributes 
      "extra" block. (Note: At this time the Mtime, Atime
      and Ctime values MAY be used on any WIN32 system.)  

      Note: all fields stored in Intel low-byte/high-byte order.

        Value      Size       Description
        -----      ----       -----------
(NTFS)  0x000a     2 bytes    Tag for this "extra" block type
        TSize      2 bytes    Size of the total "extra" block
        Reserved   4 bytes    Reserved for future use
        Tag1       2 bytes    NTFS attribute tag value #1
        Size1      2 bytes    Size of attribute #1, in bytes
        (var)      Size1      Attribute #1 data
         .
         .
         .
         TagN       2 bytes    NTFS attribute tag value #N
         SizeN      2 bytes    Size of attribute #N, in bytes
         (var)      SizeN      Attribute #N data

       For NTFS, values for Tag1 through TagN are as follows:
       (currently only one set of attributes is defined for NTFS)

         Tag        Size       Description
         -----      ----       -----------
         0x0001     2 bytes    Tag for attribute #1 
         Size1      2 bytes    Size of attribute #1, in bytes
         Mtime      8 bytes    File last modification time
         Atime      8 bytes    File last access time
         Ctime      8 bytes    File creation time
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

با این کار می توانید مقادیر دیگری را ارائه دهید. دقیقاً مورد نظر Creation time وت Last modification timeبشر

اجرای کاملاً ساده نیست.

  1. به یک کتابخانه زیپ نیاز دارد که این را می نویسد NTFS extra پشتیبانی از زمینه در اینجا با شارپزیپلیب روبرو شدم. از آگوست 2023 به روز نشده است ، اما برای یک منطق بسته سمت سرور متناسب است.
  2. برای نوشتن قسمت کد طول می کشد:
var zipMemoryStream = new System.IO.MemoryStream();

using var zipStream = new ZipOutputStream(zipMemoryStream)
{
    IsStreamOwner = false // Prevent from disposing the memory stream
};

var zipEntry = new ZipEntry(myFilename);

byte[] ntfsExtraData = CreateNtfsExtraField(
    creationTime: myDocument.CreatedAt,
    modifiedTime: myDocument.ChangedAt,
    lastAccessTime: myDocument.ChangedAt
);

zipEntry.ExtraData = ntfsExtraData;

zipStream.PutNextEntry(zipEntry);

await fileStream.CopyToAsync(zipStream, ct);

fileStream.Dispose();
...

private static byte[] CreateNtfsExtraField(DateTime creationTime, DateTime modifiedTime, DateTime lastAccessTime)
{
    // NTFS extra field structure:
    // [Header ID (2 bytes)][Data Size (2 bytes)][Reserved (4 bytes)][Tag (2 bytes)][Content Size (2 bytes)][Timestamps (24 bytes)]

    // Constants
    ushort headerId = 0x000A; // NTFS field
    ushort tag = 0x0001;      // Attribute Tag - "Standard information"

    // Time conversion: DateTime -> Windows FILETIME (ticks since 1601-01-01)
    long creationFileTime = creationTime.ToFileTimeUtc();
    long accessFileTime = lastAccessTime.ToFileTimeUtc();
    long modifiedFileTime = modifiedTime.ToFileTimeUtc();

    using (var ms = new MemoryStream())
    using (var writer = new BinaryWriter(ms))
    {
        // Write Header ID and Size Placeholder
        writer.Write(headerId);
        writer.Write((ushort)32); // Data Size: Reserved(4) + Tag(2) + Size(2) + 24 bytes

        writer.Write(0); // Reserved (4 bytes)

        // Attribute Tag
        writer.Write(tag);
        writer.Write((ushort)24); // Content Size (24 bytes for 3 timestamps)

        // Write the timestamps (each 8 bytes)
        writer.Write(modifiedFileTime);
        writer.Write(accessFileTime);
        writer.Write(creationFileTime);

        return ms.ToArray();
    }
}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

و voilà: ابرداده به دلخواه است 🙂

ابرداده سازگار

(توجه: “آخرین دسترسی” هنگام باز شدن گفتگوی ابرداده تغییر می کند ؛ از قبل متناسب است ؛))

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا