Skip to content
This repository has been archived by the owner on Feb 1, 2021. It is now read-only.

Commit

Permalink
make form upload support crc32 check by default
Browse files Browse the repository at this point in the history
  • Loading branch information
jemygraw committed Aug 20, 2017
1 parent 228e890 commit d4630d2
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 49 deletions.
1 change: 1 addition & 0 deletions storage/bucket_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ func init() {
}
mac = qbox.NewMac(testAK, testSK)
cfg := Config{}
cfg.Zone = &Zone_z0
bucketManager = NewBucketManager(mac, &cfg)
operationManager = NewOperationManager(mac, &cfg)
formUploader = NewFormUploader(&cfg)
Expand Down
81 changes: 32 additions & 49 deletions storage/form_upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,17 @@ import (
"fmt"
"hash/crc32"
"io"
"io/ioutil"
"mime/multipart"
"net/textproto"
"os"
"path"
"path/filepath"
"strconv"
"strings"

"github.com/qiniu/x/rpc.v7"
)

// 文件上传后进行crc32校验的方式
const (
DontCheckCrc = 0
CalcAndCheckCrc = 1
CheckCrc = 2
)

// PutExtra 为表单上传的额外可选项
type PutExtra struct {
// 可选,用户自定义参数,必须以 "x:" 开头。若不以x:开头,则忽略。
Expand All @@ -32,13 +25,6 @@ type PutExtra struct {
// 可选,当为 "" 时候,服务端自动判断。
MimeType string

Crc32 uint32

// CheckCrc == 0 (DontCheckCrc): 表示不进行 crc32 校验
// CheckCrc == 1 (CalcAndCheckCrc): 对于 Put 等同于 CheckCrc = 2;对于 PutFile 会自动计算 crc32 值
// CheckCrc == 2 (CheckCrc): 表示进行 crc32 校验,且 crc32 值就是上面的 Crc32 变量
CheckCrc uint32

// 上传事件:进度通知。这个事件的回调函数应该尽可能快地结束。
OnProgress func(fsize, uploaded int64)
}
Expand Down Expand Up @@ -118,13 +104,6 @@ func (p *FormUploader) putFile(
extra = &PutExtra{}
}

//if not set, enable the crc32 check
if extra.CheckCrc == DontCheckCrc || extra.CheckCrc == CalcAndCheckCrc {
extra.Crc32, err = getFileCrc32(f)
if err != nil {
return
}
}
return p.put(ctx, ret, uptoken, key, hasKey, f, fsize, extra, filepath.Base(localFile))
}

Expand Down Expand Up @@ -192,14 +171,42 @@ func (p *FormUploader) put(
return
}

//read data
var dataBytes []byte
dataBytes, err = ioutil.ReadAll(data)
if err != nil {
return
}

h := crc32.NewIEEE()
h.Write(dataBytes)
crc32 := h.Sum32()

//write crc32
writer.WriteField("crc2", fmt.Sprintf("%d", crc32))
//write file
head := make(textproto.MIMEHeader)
head.Set("Content-Disposition", fmt.Sprintf(`form-data; name="file"; filename="%s"`,
escapeQuotes(fileName)))
if extra.MimeType != "" {
head.Set("Content-Type", extra.MimeType)
}

_, err = writer.CreatePart(head)
if err != nil {
return
}

lastLine := fmt.Sprintf("\r\n--%s--\r\n", writer.Boundary())
r := strings.NewReader(lastLine)

bodyLen := int64(-1)
if size >= 0 {
bodyLen = int64(b.Len()) + size + int64(len(lastLine))
}
mr := io.MultiReader(&b, data, r)

dataReader := bytes.NewReader(dataBytes)
mr := io.MultiReader(&b, dataReader, r)

contentType := writer.FormDataContentType()
err = p.client.CallWith64(ctx, ret, "POST", upHost, contentType, mr, bodyLen)
Expand Down Expand Up @@ -256,8 +263,8 @@ func (p *readerWithProgress) Read(b []byte) (n int, err error) {
return
}

func writeMultipart(
writer *multipart.Writer, uptoken, key string, hasKey bool, extra *PutExtra, fileName string) (err error) {
func writeMultipart(writer *multipart.Writer, uptoken, key string, hasKey bool,
extra *PutExtra, fileName string) (err error) {

//token
if err = writer.WriteField("token", uptoken); err != nil {
Expand All @@ -283,22 +290,6 @@ func writeMultipart(
}
}

//extra.CheckCrc
if extra.CheckCrc != 0 {
err = writer.WriteField("crc32", strconv.FormatInt(int64(extra.Crc32), 10))
if err != nil {
return
}
}

//file
head := make(textproto.MIMEHeader)
head.Set("Content-Disposition", fmt.Sprintf(`form-data; name="file"; filename="%s"`, escapeQuotes(fileName)))
if extra.MimeType != "" {
head.Set("Content-Type", extra.MimeType)
}

_, err = writer.CreatePart(head)
return err
}

Expand All @@ -307,11 +298,3 @@ var quoteEscaper = strings.NewReplacer("\\", "\\\\", `"`, "\\\"")
func escapeQuotes(s string) string {
return quoteEscaper.Replace(s)
}

func getFileCrc32(f *os.File) (uint32, error) {
h := crc32.NewIEEE()
_, err := io.Copy(h, f)
f.Seek(0, 0)

return h.Sum32(), err
}

0 comments on commit d4630d2

Please sign in to comment.