Avoid b2 temporary file.

If source can provide SHA1 hash we don't copy input to a temporary file.

Fixes #358
This commit is contained in:
klauspost 2016-02-19 15:45:32 +01:00 committed by Nick Craig-Wood
parent ef06371c93
commit 758c7f2d84

View file

@ -878,34 +878,42 @@ func urlEncode(in string) string {
func (o *Object) Update(in io.Reader, src fs.ObjectInfo) (err error) { func (o *Object) Update(in io.Reader, src fs.ObjectInfo) (err error) {
size := src.Size() size := src.Size()
modTime := src.ModTime() modTime := src.ModTime()
calculatedSha1, _ := src.Hash(fs.HashSHA1)
// Open a temp file to copy the input // If source cannot provide the hash, copy to a temporary file
fd, err := ioutil.TempFile("", "rclone-b2-") // and calculate the hash while doing so.
if err != nil { // Then we serve the temporary file.
return err if calculatedSha1 == "" {
} // Open a temp file to copy the input
_ = os.Remove(fd.Name()) // Delete the file - may not work on Windows fd, err := ioutil.TempFile("", "rclone-b2-")
defer func() { if err != nil {
_ = fd.Close() // Ignore error may have been closed already return err
_ = os.Remove(fd.Name()) // Delete the file - may have been deleted already }
}() _ = os.Remove(fd.Name()) // Delete the file - may not work on Windows
defer func() {
_ = fd.Close() // Ignore error may have been closed already
_ = os.Remove(fd.Name()) // Delete the file - may have been deleted already
}()
// Copy the input while calculating the sha1 // Copy the input while calculating the sha1
hash := sha1.New() hash := sha1.New()
teed := io.TeeReader(in, hash) teed := io.TeeReader(in, hash)
n, err := io.Copy(fd, teed) n, err := io.Copy(fd, teed)
if err != nil { if err != nil {
return err return err
} }
if n != size { if n != size {
return fmt.Errorf("Read %d bytes expecting %d", n, size) return fmt.Errorf("Read %d bytes expecting %d", n, size)
} }
calculatedSha1 := fmt.Sprintf("%x", hash.Sum(nil)) calculatedSha1 = fmt.Sprintf("%x", hash.Sum(nil))
// Rewind the temporary file // Rewind the temporary file
_, err = fd.Seek(0, 0) _, err = fd.Seek(0, 0)
if err != nil { if err != nil {
return err return err
}
// Set input to temporary file
in = fd
} }
// Get upload URL // Get upload URL
@ -971,7 +979,7 @@ func (o *Object) Update(in io.Reader, src fs.ObjectInfo) (err error) {
Method: "POST", Method: "POST",
Absolute: true, Absolute: true,
Path: UploadURL, Path: UploadURL,
Body: fd, Body: in,
ExtraHeaders: map[string]string{ ExtraHeaders: map[string]string{
"Authorization": AuthorizationToken, "Authorization": AuthorizationToken,
"X-Bz-File-Name": urlEncode(o.fs.root + o.remote), "X-Bz-File-Name": urlEncode(o.fs.root + o.remote),