Attempt
This commit is contained in:
parent
74ff05d9c9
commit
4e389210dc
66
archive.py
66
archive.py
|
|
@ -136,16 +136,16 @@ def zip_local_file_header(filename: str, filepath: str) -> bytes:
|
|||
buffer[12:14] = mtime.day | (mtime.month << 5) | ((mtime.year - 1980) << 9)
|
||||
|
||||
# Field 6: crc-32 of uncompressed data (buffer[14:18])
|
||||
buffer[14:18] = crc32(filepath).to_bytes(4)
|
||||
buffer[14:18] = crc32(filepath).to_bytes(4, byteorder='little')
|
||||
|
||||
# Field 7: compressed size (buffer[18:22])
|
||||
buffer[18:22] = stat.st_size.to_bytes(4)
|
||||
buffer[18:22] = stat.st_size.to_bytes(4, byteorder='little')
|
||||
|
||||
# Field 8: uncompressed size (buffer[22:26])
|
||||
buffer[22:26] = stat.st_size.to_bytes(4)
|
||||
buffer[22:26] = stat.st_size.to_bytes(4, byteorder='little')
|
||||
|
||||
# Field 9: filename length (buffer[26:28])
|
||||
buffer[26:28] = len(filename).to_bytes(4)
|
||||
buffer[26:28] = len(filename).to_bytes(2, byteorder='little')
|
||||
|
||||
# Field 10: extra field length (buffer[28:30])
|
||||
|
||||
|
|
@ -155,7 +155,7 @@ def zip_local_file_header(filename: str, filepath: str) -> bytes:
|
|||
return buffer
|
||||
|
||||
|
||||
def zip_central_directory_file_header(filename: str, filepath: str) -> bytes:
|
||||
def zip_central_directory_file_header(filename: str, filepath: str, offset: int) -> bytes:
|
||||
buffer_size = 46 + len(filename)
|
||||
buffer = bytearray(buffer_size)
|
||||
stat = os.stat(filepath)
|
||||
|
|
@ -179,16 +179,16 @@ def zip_central_directory_file_header(filename: str, filepath: str) -> bytes:
|
|||
buffer[14:16] = mtime.day | (mtime.month << 5) | ((mtime.year - 1980) << 9)
|
||||
|
||||
# Field 6: crc-32 of uncompressed data (buffer[16:20])
|
||||
buffer[16:20] = crc32(filepath).to_bytes(4)
|
||||
buffer[16:20] = crc32(filepath).to_bytes(4, byteorder='little')
|
||||
|
||||
# Field 7: compressed size (buffer[20:24])
|
||||
buffer[20:24] = stat.st_size.to_bytes(4)
|
||||
buffer[20:24] = stat.st_size.to_bytes(4, byteorder='little')
|
||||
|
||||
# Field 8: uncompressed size (buffer[24:28])
|
||||
buffer[24:28] = stat.st_size.to_bytes(4)
|
||||
buffer[24:28] = stat.st_size.to_bytes(4, byteorder='little')
|
||||
|
||||
# Field 9: filename length (buffer[28:30])
|
||||
buffer[28:30] = len(filename).to_bytes(4)
|
||||
buffer[28:30] = len(filename).to_bytes(2, byteorder='little')
|
||||
|
||||
# Field 10: extra field length (buffer[30:32])
|
||||
|
||||
|
|
@ -208,11 +208,45 @@ def zip_central_directory_file_header(filename: str, filepath: str) -> bytes:
|
|||
return buffer
|
||||
|
||||
|
||||
def zip_end_of_central_directory(items_number: int, central_directory_size: int, central_directory_offset: int):
|
||||
buffer = bytearray(22)
|
||||
# Field 1: End of central directory signature = 0x06054b50 (buffer[0:4])
|
||||
buffer[0:4] = b'\x06\x05\x4b\x50'
|
||||
|
||||
# Field 2: Number of this disk (buffer[4:6])
|
||||
|
||||
# Field 3: Disk where central directory starts (buffer[6:8])
|
||||
|
||||
# Field 4: Number of central directory records on this disk (buffer[8:10])
|
||||
buffer[8:10] = items_number.to_bytes(2, byteorder='little')
|
||||
|
||||
# Field 5: Total number of central directory records (buffer[10:12])
|
||||
buffer[10:12] = items_number.to_bytes(2, byteorder='little')
|
||||
|
||||
# Field 6: Size of central directory in bytes (buffer[12:16])
|
||||
buffer[12:16] = central_directory_size.to_bytes(4, byteorder='little')
|
||||
|
||||
# Field 7: Offset of start of central directory (buffer[16:20])
|
||||
buffer[16:20] = central_directory_size.to_bytes(4, byteorder='little')
|
||||
|
||||
# Field 8: Comment length (buffer[20:22])
|
||||
|
||||
# Field 9: Comment (buffer[22:])
|
||||
return buffer
|
||||
|
||||
|
||||
class ZipSender(ArchiveSender):
|
||||
def response(self):
|
||||
def generate():
|
||||
local_offsets = dict()
|
||||
current_byte = 0
|
||||
|
||||
for name, file in self.files.items():
|
||||
yield zip_local_file_header(name, file)
|
||||
local_offsets[name] = current_byte
|
||||
chunk = zip_local_file_header(name, file)
|
||||
current_byte += chunk
|
||||
|
||||
yield chunk
|
||||
|
||||
with open(file, 'rb') as f:
|
||||
while True:
|
||||
|
|
@ -221,8 +255,20 @@ class ZipSender(ArchiveSender):
|
|||
if len(bytes) == 0:
|
||||
break
|
||||
|
||||
current_byte += len(bytes)
|
||||
yield bytes
|
||||
|
||||
central_directory_size = 0
|
||||
centra_directory_offset = current_byte
|
||||
|
||||
for name, file, in self.files.items():
|
||||
chunk = zip_central_directory_file_header(name, file, local_offsets[name])
|
||||
central_directory_size += len(chunk)
|
||||
current_byte += len(chunk)
|
||||
yield chunk
|
||||
|
||||
yield zip_end_of_central_directory(len(self.files.items()), central_directory_size, centra_directory_offset)
|
||||
|
||||
return Response(
|
||||
generate(),
|
||||
mimetype='application/zip',
|
||||
|
|
|
|||
Loading…
Reference in New Issue