c# - Hash a file as its being recived -
end goal: users uploading large number of files in different sizes web site. , dont want duplicate files on disk.
the solution have been using simple sh1 hash of file when uploaded. code this:
public static string hashfile(string filename) { using (filestream stream = file.openread(filename)) { sha1managed sha = new sha1managed(); byte[] checksum = sha.computehash(stream); string sendchecksum = bitconverter.tostring(checksum).replace("-",string.empty); return sendchecksum; } }
this "works" fine smaller files, big pain when file 30gb. hash file im reciving client. file client in "chunks" , size of chunk not static.
code recives file.
int chunk = context.request["chunk"] != null ? int.parse(context.request["chunk"]) : 0; int chunks = context.request["chunks"] != null ? int.parse(context.request["chunks"]) : 0; string filename = context.request["name"] != null ? context.request["name"] : string.empty; httppostedfile fileupload = context.request.files[0]; string fullfilepath = path.combine(sitesettings.uploadtempfolder, filename); using (var fs = new filestream(fullfilepath, chunk == 0 ? filemode.create : filemode.append)) { var buffer = new byte[fileupload.inputstream.length]; fileupload.inputstream.read(buffer, 0, buffer.length); fs.write(buffer, 0, buffer.length); **// here want hash, when have file data in memory.** }
you can create own stream :)
public class actionstream : stream { private readonly stream _innerstream; private readonly action<byte[], int, int> _readaction; public actionstream(stream innerstream, action<byte[], int, int> readaction) { _innerstream = innerstream; _readaction = readaction; } public override bool canread => true; public override bool canseek => false; public override bool canwrite => false; public override long length => _innerstream.length; public override long position { { return _innerstream.position; } set { throw new notsupportedexception(); } } public override void flush() { } public override int read(byte[] buffer, int offset, int count) { var bytesread = _innerstream.read(buffer, offset, count); _readaction(buffer, offset, bytesread); return bytesread; } public override long seek(long offset, seekorigin origin) { throw new notsupportedexception(); } protected override void dispose(bool disposing) { if (disposing) { _innerstream.dispose(); } base.dispose(disposing); } public override void setlength(long value) { throw new notsupportedexception(); } public override void write(byte[] buffer, int offset, int count) { throw new notsupportedexception(); } }
this allows bind 2 stream operations you're doing:
using (var fs = new filestream(path, chunk == 0 ? filemode.create : filemode.append)) { var = new actionstream(fileupload.inputstream, (buffer, offset, bytesread) => { fs.write(buffer, offset, bytesread); }); var sha = new sha1managed(); var checksum = sha.computehash(as); }
this assumes sha1manager
reads through every single byte of input stream in order - should check that. i'm pretty sure how works, though :)
Comments
Post a Comment