filetype icon indicating copy to clipboard operation
filetype copied to clipboard

The header reads 261 bytes and then wants to use the full file data, so it's missing 261 bytes. How to handle this gracefully

Open applyfly opened this issue 5 years ago • 4 comments

The test case following:

func (o *OSSESSuite) Test_Upload_FileStream_SetContentType2() {
	file, err := os.Open("../../test/assets/HgWFAEPozfVdcst")
	assert.NoError(o.T(), err)

	// Gets the file size, equal to true.
	info, err := file.Stat()
	assert.Equal(o.T(), int64(87064), info.Size())

	head := make([]byte, 261)
	_, err = file.Read(head)
	assert.NoError(o.T(), err)
	match, err := filetype.Match(head)
	assert.Equal(o.T(), "image/png", match.MIME.Value)

	// Gets the file size, equal to true.
	info, err = file.Stat()
	assert.NoError(o.T(), err)
	assert.Equal(o.T(), int64(87064), info.Size())

	o.client.SetObjectContentType(match.MIME.Value)
	err = o.client.PutObject("HgWFAEPozfVdcst", file)
	assert.NoError(o.T(), err)
}

The test case result:

=== RUN   TestOSSESSuite
--- FAIL: TestOSSESSuite (0.03s)
=== RUN   TestOSSESSuite/Test_Upload_FileStream_SetContentType2
    --- FAIL: TestOSSESSuite/Test_Upload_FileStream_SetContentType2 (0.03s)
        osses_test.go:105: 
            	Error Trace:	osses_test.go:105
            	Error:      	Received unexpected error:
            	            	Put http://hello-world.oss-cn-beijing.aliyuncs.com/HgWFAEPozfVdcst: net/http: HTTP/1.x transport connection broken: http: ContentLength=87064 with Body length 86803
            	Test:       	TestOSSESSuite/Test_Upload_FileStream_SetContentType2
FAIL

The focus is on: ContentLength=87064 with Body length 86803

applyfly avatar Mar 31 '20 11:03 applyfly

file reader stream is stateful and when the stream is consumed, data will be drained. The simplest way to solve this is to reinitialize the reader by opening the file again or, alternatively, writing head data back into the reader buffer via file.WriteAt(head, 0)

h2non avatar Mar 31 '20 16:03 h2non

@h2non I tried to write it, but it didn't work

applyfly avatar Apr 01 '20 14:04 applyfly

You could just close the first file reader stream, then open it again and read the full content.

h2non avatar Apr 01 '20 14:04 h2non

@helloshaohua There are two options:

  1. As your case is a file you can use Seek method _, err := file.Seek(0, io.SeekStart). Next read start from zero;
  2. For any case is to use []byte buffer, like you did, but also chain readers with io.MultiReader
file, err := os.Open("../../test/assets/HgWFAEPozfVdcst")
// ...
head := make([]byte, 262)
_, _ = io.ReadFull(file, head)
match, err := filetype.Match(head)
// ...
reader := io.MultiReader(bytes.NewBuffer(head), file)
// ...
err = o.client.PutObject("HgWFAEPozfVdcst", reader) // put io.MultiReader

p.s. Don't forget to close the file/reader

sergolius avatar May 29 '23 16:05 sergolius