简体   繁体   中英

RubyZip set file timestamps

I have been banging my head the whole day on this, maybe you can help? I am zipping the file with RubyZip and I need to set the time of that file creation/update/modification to the certain time in time zone (which depends on the client time zone I have in the @time_zone variable).

I know it is most likely super incorrect, and I have taken that magic string 'UT\\x5\\0\\x3\\250$\\r@Ux\\0\\0' from the RubyZip tests file, and I have no idea what this is. LOL. However - I have made it work now on my PC. It really zips the file and sets the correct timestamps for it according to the specified time zone.

BUT - it doesn't work on the app server, which as OS time zone is in UTC time zone. It generates some other time for files which doesn't match.

Here's how far I made it work:

def save_to_zip(file_path)
  Zip::OutputStream.open(file_path) do |out|
    @sheets.each do |csv|
      name = csv.name
      extra = time_for_zip
      out.put_next_entry("#{name}.#{@file_extension}", nil, extra)
      tmpfile = csv.tmpfile
      tmpfile.close
      source = File.open(tmpfile.path, 'r')
      source.each do |line|
        out.write(line)
      end
    end
  end
end

def time_for_zip
  return nil if @time_zone.blank?

  timestamp = Zip::ExtraField.new('UT\x5\0\x3\250$\r@Ux\0\0')
  localtime_str = Time.now.in_time_zone(@time_zone).strftime("%Y-%m-%dT%H:%M:%S")
  dos_time_in_store_tz = ::Zip::DOSTime.parse(localtime_str)

  timestamp['UniversalTime'].ctime = dos_time_in_store_tz
  timestamp['UniversalTime'].atime = dos_time_in_store_tz
  timestamp['UniversalTime'].mtime = dos_time_in_store_tz

  timestamp
end

Can you please tell me how can I set the file time correctly inside the zip file?

Really appreciated...

Maris

Solved like this:

    def save_to_zip(file_path)
  Zip::OutputStream.open(file_path) do |out|
    @sheets.each do |csv|
      name = csv.name
      tmpfile = csv.tmpfile
      tmpfile.close
      source = File.open(tmpfile.path, 'r')
      zip_entry = Zip::Entry.new(out, "#{name}.#{@file_extension}", nil, nil, nil, nil, nil, nil, time_for_zip(source.ctime))
      out.put_next_entry(zip_entry)
      source.each do |line|
        out.write(line)
      end
    end
  end
end

def time_for_zip(file_time)
  return Zip::DOSTime.at(file_time) if @time_zone.blank?

  Zip::DOSTime.parse(file_time.utc.in_time_zone(@time_zone).strftime("%Y-%m-%d %H:%M:%S"))
end

Kudos to this thread: https://github.com/rubyzip/rubyzip/pull/40

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM