1 package mimetype_test 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 8 "github.com/gabriel-vasile/mimetype" 9 ) 10 11 // Pure io.Readers (meaning those without a Seek method) cannot be read twice. 12 // This means that once DetectReader has been called on an io.Reader, that reader 13 // is missing the bytes representing the header of the file. 14 // To detect the MIME type and then reuse the input, use a buffer, io.TeeReader, 15 // and io.MultiReader to create a new reader containing the original, unaltered data. 16 // 17 // If the input is an io.ReadSeeker instead, call input.Seek(0, io.SeekStart) 18 // before reusing it. 19 func Example_detectReader() { 20 testBytes := []byte("This random text has a MIME type of text/plain; charset=utf-8.") 21 input := bytes.NewReader(testBytes) 22 23 mtype, recycledInput, err := recycleReader(input) 24 25 // Verify recycledInput contains the original input. 26 text, _ := io.ReadAll(recycledInput) 27 fmt.Println(mtype, bytes.Equal(testBytes, text), err) 28 // Output: text/plain; charset=utf-8 true <nil> 29 } 30 31 // recycleReader returns the MIME type of input and a new reader 32 // containing the whole data from input. 33 func recycleReader(input io.Reader) (mimeType string, recycled io.Reader, err error) { 34 // header will store the bytes mimetype uses for detection. 35 header := bytes.NewBuffer(nil) 36 37 // After DetectReader, the data read from input is copied into header. 38 mtype, err := mimetype.DetectReader(io.TeeReader(input, header)) 39 if err != nil { 40 return 41 } 42 43 // Concatenate back the header to the rest of the file. 44 // recycled now contains the complete, original data. 45 recycled = io.MultiReader(header, input) 46 47 return mtype.String(), recycled, err 48 } 49