Thanks for the pointer. I also found this helpful Asynchronously Split an io.Reader in Go (golang) « Rodaine <http://rodaine.com/2015/04/async-split-io-reader-in-golang/> but I'm still missing something.
Version 1: the uploaded file is 1024 bytes extra at the end (too big): mimebuf := make([]byte, 1024) _, err = file.Read(mimebuf) mime := mimemagic.Match("", mimebuf) fileReader := io.MultiReader(bytes.NewReader(mimebuf), file) checksum := md5.New() b := io.TeeReader(fileReader, checksum) md5hex := hex.EncodeToString(checksum.Sum(nil)) // Save file io.Copy(f, b) Version 2: the uploaded file is truncated by 1024 byte (too small): (this makes sense since the first 1024 bytes of file was consumed) mimebuf := make([]byte, 1024) _, err = file.Read(mimebuf) mime := mimemagic.Match("", mimebuf) checksum := md5.New() // Adding file.Seek(0,0) here does not fix this issue b := io.TeeReader(file, checksum) md5hex := hex.EncodeToString(checksum.Sum(nil)) // Save file io.Copy(f, b) What is incorrect which is causing this? How do I get the goldilocks version that's just right? On Saturday, July 2, 2016 at 3:18:51 AM UTC-4, Tamás Gulácsi wrote: > > > 2016. július 2., szombat 8:15:19 UTC+2 időpontban Sri G a következőt írta: >> >> I'm working on receiving uploads through a form. >> >> The tricky part is validation. >> >> I attempt to read the first 1024 bytes to check the mime of the file and >> then if valid read the rest and hash it and also save it to disk. Reading >> the mime type is successful and I've gotten it to work by chaining >> TeeReader but it seems very hackish. Whats the idiomatic way to do this? >> >> I'm trying something like this: >> >> >> // Parse my multi part form >> ... >> // Get file handle >> file, err := fh.Open() >> >> var a bytes.Buffer >> >> io.CopyN(&a, file, 1024) >> >> mime := mimemagic.Match("", a.Bytes()) >> // Check mime type (this works fine) >> >> I'm trying to seek a stream so this should be no-op >> file.Seek(0, 0) >> >> The file stored on disk is 1KB larger than the original so it appears to >> be re-copying the entire file and appending it to bytes.Buffer >> io.Copy(&a, file) >> >> checksum := md5.New() >> b := io.TeeReader(&a, checksum) >> >> md5hex := hex.EncodeToString(checksum.Sum(nil)) >> fmt.Println("md5=", md5hex) >> >> //Open file f for writing to disk >> ... >> //Save file >> io.Copy(f, b) >> >> >> Checked the md5 of (1KB of orig + orig), and (orginal - first 1 KB), >> neither match the md5 of the file being hashed. >> >> Why can't I append the rest of the stream to the byte buffer to get the >> complete file in memory and why is the byte buffer being "consumed"? >> >> I simply need to read the same array of byte multiple times, I don't need >> to "copy" them. I'm coming from a C background so I'm wondering what is >> going on behind the scenes as well. >> > > If you know you'll have to read the whole file into memory, then do that, > and use bytes.NewReader to create a reader for that byte slice. > > If you read partly, to decide whether to go on, then use fh.Read or > io.ReadAtLeast with a byte slice. > > If you read sth, then want to read the whole from the beginning, construct > a Reader with io.MultiReader(bytes.NewReader(b), fh). > > You can combine these approaches, but if the while file size is less than > a few KiB, I think it is easier, simpler and more performant (!) to read > the whole file up into memory, > into a bytes.Buffer, and construct the needed readers with > bytes.NewReader(buf.Bytes()). > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.