700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > go文件上传断点续传功能

go文件上传断点续传功能

时间:2022-03-30 05:29:04

相关推荐

go文件上传断点续传功能

go断点续传功能

断点续传功能,减少服务器文件重复存储. 提升上传响应速度

使用两种思路进行续传功能

注意: 文件使用文件名称进行唯一文件进行判断, 不具有文件唯一性.如果使用于生产环境. 需要处理文件上传文件名称问题

思路1:

思路1: 使用零时文件记录中断位置.

1.文件上传时,先创建上传一个新的文件

2.创建记录中断位置的临时文件

3.设置文件读写偏移量

4.上传完成后,删除临时文件

func upload1(r *http.Request) (int,error) {// 获取上传文件upfile, fileHeader, err := r.FormFile("file")if err != nil {return 0, errors.New("上传文件错误")}headerByte, _ := json.Marshal(fileHeader.Header)log.Printf("当前文件:Filename - >{%s}, Size -> {%v}, FileHeader -> {%s}", fileHeader.Filename, fileHeader.Size, string(headerByte))// 新文件创建filePath := "./" + fileHeader.FilenamefileBool, err := isFileExists(filePath)if fileBool && err == nil {fmt.Println("文件已存在")} else {newfile, err := os.Create(filePath)defer newfile.Close()if err != nil {return 0, errors.New("创建文件失败")}}// 上传文件开始位置start := "0"// 查询本地是否有断点记录var breakPointFile *os.FilebreakPointFilePath := filePath + ".txt"breakPointFileBool, err := isFileExists(breakPointFilePath)// 如果文件存在 但断点记录不存在 则文件已上传if fileBool && !breakPointFileBool {return 0, errors.New("文件已存在, 不继续上传")}//fmt.Println("断点文件检测:", breakPointFileBool,err)if breakPointFileBool && err == nil {// 读取断点位置breakPointFile, err = os.OpenFile(breakPointFilePath,os.O_CREATE|os.O_RDWR,os.ModePerm)defer breakPointFile.Close()if err != nil {return 0, errors.New("断点文件打开失败")}res, _ := ioutil.ReadAll(breakPointFile)fmt.Println("断点文件写入字段长度:",string(res))start = string(res)} else {// 创建断点文件breakPointFile ,err = os.Create(breakPointFilePath)defer breakPointFile.Close()if err != nil {return 0, errors.New("断点文件创建失败")}len, err := breakPointFile.WriteString("0")if len <= 0 || err != nil {return 0, errors.New("断点文件写入失败")}fmt.Println("断点文件创建成功")}// 进行断点上传// 打开之前上传文件file, err := os.OpenFile(filePath,os.O_CREATE|os.O_WRONLY,os.ModePerm)defer file.Close()if err != nil {return 0, errors.New("打开之前上传文件不存在")}// 将数据写入文件count,_:=strconv.ParseInt(start,10,64)fmt.Println("已上传:",count)// 设置读,写的偏移量upfile.Seek(count,0)file.Seek(count,0)data:=make([]byte,1024,1024)upTotal := 0for {total, err := upfile.Read(data)if err == io.EOF{// 删除文件 需要先关闭改文件breakPointFile.Close()err := os.Remove(breakPointFilePath)if err != nil {fmt.Println("临时记录文件删除失败", err)}fmt.Println("文件复制完毕")break}len, err := file.Write(data[:total])if err != nil {return 0, errors.New("文件上传失败")}upTotal += len// 记录上传长度count += int64(len)breakPointFile.Seek(0, 0)breakPointFile.WriteString(strconv.Itoa(int(count)))// 模拟断开//if count > 4438903 {//log.Fatal("模拟上传中断")//}}fmt.Println("文件上传长度:", upTotal)return upTotal, nil}

思路2:

使用获取上传文件大小进行判断

1.文件上传时,先创建上传一个新的文件

2.判断已上传的文件和正在上传的文件的文件大小进行判断

3.设置文件读写偏移量

func upload2(r *http.Request) (int,error) {// 获取上传文件upfile, fileHeader, err := r.FormFile("file")if err != nil {return 0, errors.New("上传文件错误")}headerByte, _ := json.Marshal(fileHeader.Header)log.Printf("当前文件:Filename - >{%s}, Size -> {%v}, FileHeader -> {%s}", fileHeader.Filename, fileHeader.Size, string(headerByte))// 新文件创建filePath := "./" + fileHeader.FilenamefileBool, err := isFileExists(filePath)if fileBool && err == nil {fmt.Println("文件已存在")} else {newfile, err := os.Create(filePath)defer newfile.Close()if err != nil {return 0, errors.New("创建文件失败")}}// 获取现在文件大小fi, _ := os.Stat(filePath)// 判断文件是否传输完成if fi.Size() == fileHeader.Size {return 0, errors.New("文件已存在, 不继续上传")}start := strconv.Itoa(int(fi.Size()))// 进行断点上传// 打开之前上传文件file, err := os.OpenFile(filePath,os.O_CREATE|os.O_WRONLY,os.ModePerm)defer file.Close()if err != nil {return 0, errors.New("打开之前上传文件不存在")}// 将数据写入文件count,_:=strconv.ParseInt(start,10,64)fmt.Println("已上传:",count)// 设置读,写的偏移量upfile.Seek(count,0)file.Seek(count,0)data:=make([]byte,1024,1024)upTotal := 0for {total, err := upfile.Read(data)if err == io.EOF{fmt.Println("文件复制完毕")break}len, err := file.Write(data[:total])if err != nil {return 0, errors.New("文件上传失败")}upTotal += len// 记录上传长度count += int64(len)// 模拟断开//if count > 4438903 {//log.Fatal("模拟上传中断")//}}fmt.Println("文件上传长度:", upTotal)return upTotal, nil}

完整代码:

package mainimport ("encoding/json""errors""fmt""io""io/ioutil""log""net/http""os""strconv")func main() {server()}// 上传func upload(w http.ResponseWriter, r *http.Request) {res, err := upload2(r)if err != nil {_, _ = w.Write([]byte(err.Error()))} else {// 保存上传节点_, _ = w.Write([]byte("上传成功:" + strconv.Itoa(res)))}}func upload2(r *http.Request) (int,error) {// 获取上传文件upfile, fileHeader, err := r.FormFile("file")if err != nil {return 0, errors.New("上传文件错误")}headerByte, _ := json.Marshal(fileHeader.Header)log.Printf("当前文件:Filename - >{%s}, Size -> {%v}, FileHeader -> {%s}", fileHeader.Filename, fileHeader.Size, string(headerByte))// 新文件创建filePath := "./" + fileHeader.FilenamefileBool, err := isFileExists(filePath)if fileBool && err == nil {fmt.Println("文件已存在")} else {newfile, err := os.Create(filePath)defer newfile.Close()if err != nil {return 0, errors.New("创建文件失败")}}// 获取现在文件大小fi, _ := os.Stat(filePath)// 判断文件是否传输完成if fi.Size() == fileHeader.Size {return 0, errors.New("文件已存在, 不继续上传")}start := strconv.Itoa(int(fi.Size()))// 进行断点上传// 打开之前上传文件file, err := os.OpenFile(filePath,os.O_CREATE|os.O_WRONLY,os.ModePerm)defer file.Close()if err != nil {return 0, errors.New("打开之前上传文件不存在")}// 将数据写入文件count,_:=strconv.ParseInt(start,10,64)fmt.Println("已上传:",count)// 设置读,写的偏移量upfile.Seek(count,0)file.Seek(count,0)data:=make([]byte,1024,1024)upTotal := 0for {total, err := upfile.Read(data)if err == io.EOF{fmt.Println("文件复制完毕")break}len, err := file.Write(data[:total])if err != nil {return 0, errors.New("文件上传失败")}upTotal += len// 记录上传长度count += int64(len)// 模拟断开//if count > 4438903 {//log.Fatal("模拟上传中断")//}}fmt.Println("文件上传长度:", upTotal)return upTotal, nil}// 上传方法1func upload1(r *http.Request) (int,error) {// 获取上传文件upfile, fileHeader, err := r.FormFile("file")if err != nil {return 0, errors.New("上传文件错误")}headerByte, _ := json.Marshal(fileHeader.Header)log.Printf("当前文件:Filename - >{%s}, Size -> {%v}, FileHeader -> {%s}", fileHeader.Filename, fileHeader.Size, string(headerByte))// 新文件创建filePath := "./" + fileHeader.FilenamefileBool, err := isFileExists(filePath)if fileBool && err == nil {fmt.Println("文件已存在")} else {newfile, err := os.Create(filePath)defer newfile.Close()if err != nil {return 0, errors.New("创建文件失败")}}// 上传文件开始位置start := "0"// 查询本地是否有断点记录var breakPointFile *os.FilebreakPointFilePath := filePath + ".txt"breakPointFileBool, err := isFileExists(breakPointFilePath)// 如果文件存在 但断点记录不存在 则文件已上传if fileBool && !breakPointFileBool {return 0, errors.New("文件已存在, 不继续上传")}//fmt.Println("断点文件检测:", breakPointFileBool,err)if breakPointFileBool && err == nil {// 读取断点位置breakPointFile, err = os.OpenFile(breakPointFilePath,os.O_CREATE|os.O_RDWR,os.ModePerm)defer breakPointFile.Close()if err != nil {return 0, errors.New("断点文件打开失败")}res, _ := ioutil.ReadAll(breakPointFile)fmt.Println("断点文件写入字段长度:",string(res))start = string(res)} else {// 创建断点文件breakPointFile ,err = os.Create(breakPointFilePath)defer breakPointFile.Close()if err != nil {return 0, errors.New("断点文件创建失败")}len, err := breakPointFile.WriteString("0")if len <= 0 || err != nil {return 0, errors.New("断点文件写入失败")}fmt.Println("断点文件创建成功")}// 进行断点上传// 打开之前上传文件file, err := os.OpenFile(filePath,os.O_CREATE|os.O_WRONLY,os.ModePerm)defer file.Close()if err != nil {return 0, errors.New("打开之前上传文件不存在")}// 将数据写入文件count,_:=strconv.ParseInt(start,10,64)fmt.Println("已上传:",count)// 设置读,写的偏移量upfile.Seek(count,0)file.Seek(count,0)data:=make([]byte,1024,1024)upTotal := 0for {total, err := upfile.Read(data)if err == io.EOF{// 删除文件 需要先关闭改文件breakPointFile.Close()err := os.Remove(breakPointFilePath)if err != nil {fmt.Println("临时记录文件删除失败", err)}fmt.Println("文件复制完毕")break}len, err := file.Write(data[:total])if err != nil {return 0, errors.New("文件上传失败")}upTotal += len// 记录上传长度count += int64(len)breakPointFile.Seek(0, 0)breakPointFile.WriteString(strconv.Itoa(int(count)))// 模拟断开//if count > 4438903 {//log.Fatal("模拟上传中断")//}}fmt.Println("文件上传长度:", upTotal)return upTotal, nil}// 判断文件或文件夹是否存在func isFileExists(path string) (bool, error) {_, err := os.Stat(path)if err == nil {return true, nil}if os.IsNotExist(err) {return false, err}return false, err}// http 服务func server() {// 注册一个上传文件服务http.HandleFunc("/upload", upload)// 监听8000端口err := http.ListenAndServe("0.0.0.0:8000",nil)if err != nil {log.Fatal("服务启动失败")}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。