func SimpleUploader(r *http.Request, w http.ResponseWriter) {
// temp folder path
chunkDirPath := "./creatives/.uploads/" + userUUID
// create folder
err = os.MkdirAll(chunkDirPath, 02750)
// Get file handle from multipart request
var file io.Reader
mr, err := r.MultipartReader()
var fileName string
// Read multipart body until the "file" part
for {
part, err := mr.NextPart()
if err == io.EOF {
break
}
if part.FormName() == "file" {
file = part
fileName = part.FileName()
fmt.Println(fileName)
break
}
}
// Create files
tempFile := chunkDirPath + "/" + fileName
dst, err := os.Create(tempFile)
defer dst.Close()
buf := make([]byte, 1024*1024)
file.Read(buf)
// write/save buffer to disk
ioutil.WriteFile(tempFile, buf, os.ModeAppend)
if http.DetectContentType(buf) != "video/mp4" {
response, _ := json.Marshal(&Response{"File upload cancelled"})
settings.WriteResponse(w, http.StatusInternalServerError, response)
return
}
// joinedFile := io.MultiReader(bytes.NewReader(buf), file)
_, err = io.Copy(dst, file)
if err != nil {
settings.LogError(err, methodName, "Error copying file")
}
response, _ := json.Marshal(&Response{"File uploaded successfully"})
settings.WriteResponse(w, http.StatusInternalServerError, response)
}
我正在上传视频文件。 在上传整个文件之前,我想做一些检查,所以我将第一个1mb保存到文件中:
buf := make([]byte, 1024*1024)
file.Read(buf)
// write/save buffer to disk
ioutil.WriteFile(tempFile, buf, os.ModeAppend)
然后,如果检查通过,我想上传文件的其余部分dst is the same file used to save the 1st 1 mb
,所以基本上我试图附加到文件:
_, err = io.Copy(dst, file)
上传的文件大小正确但文件已损坏(无法播放视频)。
我还尝试了什么? :加入读者并保存到新文件。但是使用这种方法,文件大小增加了1 MB并且已损坏。
joinedFile := io.MultiReader(bytes.NewReader(buf), file)
_, err = io.Copy(newDst, joinedFile)
请帮助。
答案 0 :(得分:1)
你通过os.Create和ioutil.WriteFile基本上打开了两次文件
问题是os.Create的返回值(dst)就像是指向该文件开头的指针。 WriteFile不会在dst指向的位置移动。你基本上是在写WriteFile,然后是在第一组字节WriteFile写的顶部的io.Copy。
首先尝试使用WriteFile(使用Create标志),然后尝试使用Append标记的os.OpenFile(而不是os.Create)将剩余的字节追加到末尾。
此外,允许客户端为您提供文件名是极其危险的,因为它可能是../../.bashrc(例如),您要用它覆盖shell init无论用户决定上传什么。
如果您自己计算文件名会更安全,并且如果您需要记住用户选择的文件名,请将其存储在数据库中,或者甚至存储在稍后加载的metadata.json类型文件中。