Reputation: 658
I've running a simple file transfer code in go
. From the server side I try to read 1024 bytes of data at a time. From client side I'm using the io.Copy
function to transfer the file. The file transfer completes successfully 70% of the time. But in 30% of time it fails. It gets stuck on connection.Read
function. Through some experiments I saw that it happens only on the occasion where previous Read
operation reads less than 1024
bytes of data.
So from my code, ideally it should read 1024
bytes of data on all successive Read
except the very last Read
where the file transfer is complete. But on some occasion if it reads less than 1024
bytes, the next Read
operation gets stuck without throwing any error. Here is my code:
Server.go
fileBuffer := make([]byte, BUFFER_SIZE) //BUFFER_SIZE is a constant of 1024
bytesRead := int64(0)
count := 0
for {
if fileSize-bytesRead < int64(BUFFER_SIZE) { //fileSize is the size of file in bytes, which I calculated earlier.
fileBuffer = make([]byte, fileSize-bytesRead)
}
fmt.Println("Reading ", BUFFER_SIZE, " bytes of data")
n, err := connection.Read(fileBuffer)
count++
fmt.Println("Completed reading", n, " bytes of data, count=", count)
file.Write(fileBuffer[0:n])
bytesRead += int64(n)
fmt.Println("So far read", bytesRead, " bytes of data")
if err != nil {
fmt.Println(err)
}
if err == io.EOF {
result.Message = "File transfer incomplete"
break
}
if bytesRead >= fileSize {
result.Message = "File transfer complete"
break
}
}
Client.go
n, err := io.Copy(conn, file)
fmt.Println(n, " bytes sent")
For my case, number of sent bytes is correct, number of received bytes is also correct on successful transfer. The problem happens for the same file.
Upvotes: 3
Views: 1154
Reputation: 7908
TL;DR: This should be all you need to copy a file.
if _, err := io.Copy(file, connection); err != nil {
// handle error
}
If you need to copy in chunks while doing some logic in between copies (for example, printing the bytes read), you can use io.CopyN
totalRead := int64(0)
for {
n, err := io.CopyN(outfile, infile, 1024)
totalRead += n
// print bytes read followed by a carriage return
fmt.Printf("Bytes read: %d\r", totalRead)
if err != nil {
if err == io.EOF {
fmt.Println() // print a newline
break
}
// handle error
}
}
Upvotes: 5