filestoraged/src/server/storage/file_info.cr

77 lines
1.6 KiB
Crystal

# For now, upload and download are sequentials.
# In a future version, we will be able to send
# arbitrary parts of each file.
# Who knows, maybe someday we will be on UDP, too.
#class SHA256
# JSON.mapping({
# chunk: Slice(UInt8)
# })
#end
module FileStorage
# 1 MB read buffer, on-disk
def self.file_reading_buffer_size
1_000_000
end
# 1 KB message data buffer, on-network
def self.message_buffer_size
1_000
end
# private function
def self.data_digest(data : Bytes)
digest = OpenSSL::Digest.new "sha256"
digest.update data
digest.hexfinal
end
# private function
def self.file_digest(file : File)
# 1M read buffer
buffer = Bytes.new(1_000_000)
io = OpenSSL::DigestIO.new(file, "SHA256")
while io.read(buffer) > 0 ; end
io.digest.hexstring
end
end
class FileStorage::Chunk
include JSON::Serializable
property n : Int32 # chunk's number
property on : Int32 # number of chunks
property digest : String # digest of the current chunk
def initialize(@n, @on, data)
@digest = FileStorage.data_digest data.to_slice
end
end
# A file has a name, a size and tags.
class FileStorage::FileInfo
include JSON::Serializable
property name : String
property size : UInt64
property nb_chunks : Int32
property digest : String
# list of SHA256, if we are on UDP
# chunks: Array(SHA256),
property tags : Array(String)
def initialize(file : File, tags = nil)
@name = File.basename file.path
@size = file.size
@digest = FileStorage.file_digest file
@nb_chunks = (@size / FileStorage.message_buffer_size).ceil.to_i
@tags = tags || [] of String
end
end