diff --git a/weed/mount/weedfs_write.go b/weed/mount/weedfs_write.go index 0bcc6f21d..dfe5a6e48 100644 --- a/weed/mount/weedfs_write.go +++ b/weed/mount/weedfs_write.go @@ -26,12 +26,14 @@ func (wfs *WFS) saveDataAsChunk(fullPath util.FullPath) filer.SaveDataAsChunkFun return } + // WantMd5 gives mount writes a real filer.ETag (server echoes Content-MD5 back). uploadOption := &operation.UploadOption{ Filename: filename, Cipher: wfs.option.Cipher, IsInputCompressed: false, MimeType: "", PairMap: nil, + WantMd5: true, } genFileUrlFn := func(host, fileId string) string { fileUrl := fmt.Sprintf("http://%s/%s", host, fileId) diff --git a/weed/operation/upload_content.go b/weed/operation/upload_content.go index 1920478b4..075087ee0 100644 --- a/weed/operation/upload_content.go +++ b/weed/operation/upload_content.go @@ -3,6 +3,8 @@ package operation import ( "bytes" "context" + "crypto/md5" + "encoding/base64" "encoding/json" "fmt" "io" @@ -39,6 +41,7 @@ type UploadOption struct { Jwt security.EncodedJwt RetryForever bool Md5 string + WantMd5 bool // compute Content-MD5 from the data when Md5 is unset and the upload is not ciphered BytesBuffer *bytes.Buffer SourceUrl string // optional: for logging when reading from a remote source MaxAttempts int // <=0 uses the default @@ -196,6 +199,14 @@ func (uploader *Uploader) UploadWithRetry(filerClient filer_pb.FilerClient, assi assignRequest.ExpectedDataSize = uint64(len(data)) } + // Hash the buffer we already hold so the server echoes Content-MD5 back as + // the chunk ETag (std-base64 of the raw digest, the form ParseUpload + // verifies). Never under cipher: the server sees only ciphertext. + if uploadOption.WantMd5 && uploadOption.Md5 == "" && !uploadOption.Cipher { + digest := md5.Sum(data) + uploadOption.Md5 = base64.StdEncoding.EncodeToString(digest[:]) + } + fileId, uploadResult, err = uploader.uploadWithRetryData(func() (fileId string, host string, auth security.EncodedJwt, err error) { // grpc assign volume if grpcAssignErr := filerClient.WithFilerClient(false, func(client filer_pb.SeaweedFilerClient) error {