go进行大文件上传

读取前端上传的文件 创建一个临时文件夹保存上传的切片数据
前端上传完成后发送请求数据到后端合并文件
合并数据时一定要确保文件的顺序

var dir, _ = os.Getwd()
var uploadPath = path.Join(dir, "uploads")
var uploadTempPath = path.Join(uploadPath, "temp")

func sayhello(w http.ResponseWriter, r *http.Request) {
	r.ParseForm() //解析参数,默认是不会解析的
	t, err := template.ParseFiles("static/index.html")
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	t.Execute(w, "张三")
	return
}
func PathExists(path string) (bool, error) {
	_, err := os.Stat(path)
	if err == nil {
		return true, nil
	}
	if os.IsNotExist(err) {
		return false, nil
	}
	return false, err
}
func uploadFile(w http.ResponseWriter, r *http.Request) {
	file, _, err := r.FormFile("file")
	// total := r.PostFormValue("total")
	index := r.PostFormValue("index")
	// size, err := strconv.ParseInt(r.PostFormValue("size"), 10, 64)
	hash := r.PostFormValue("hash")
	// name := r.PostFormValue("name")
	nameList, err := ioutil.ReadDir(uploadPath)
	m := map[string]interface{}{
		"code": 46900,
		"msg":  "文件已上传",
	}
	result, _ := json.MarshalIndent(m, "", "    ")
	for _, name := range nameList {
		tmpName := strings.Split(name.Name(), "_")[0]
		if tmpName == hash {
			fmt.Fprintf(w, string(result))
			return
		}
	}

	chunksPath := path.Join(uploadTempPath, hash, "/")

	isPathExists, err := PathExists(chunksPath)
	if !isPathExists {
		err = os.MkdirAll(chunksPath, os.ModePerm)
	}
	destFile, err := os.OpenFile(path.Join(chunksPath+"/"+hash+"-"+index), syscall.O_CREAT|syscall.O_WRONLY, 0777)
	reader := bufio.NewReader(file)
	writer := bufio.NewWriter(destFile)
	buf := make([]byte, 1024*1024) // 1M buf
	for {
		n, err := reader.Read(buf)
		if err == io.EOF {
			writer.Flush()
			break
		} else if err != nil {
			return
		} else {
			writer.Write(buf[:n])
		}
	}

	defer file.Close()
	defer destFile.Close()
	if err != nil {
		log.Fatal("%v", err)
	}
}
// 合并文件
func chunks(w http.ResponseWriter, r *http.Request) {
	// total, _ := strconv.Atoi(r.PostFormValue("total"))
	// index := r.PostFormValue("index")
	size, _ := strconv.ParseInt(r.PostFormValue("size"), 10, 64)
	hash := r.PostFormValue("hash")
	name := r.PostFormValue("name")

	toSize, _ := DirSize(path.Join(uploadTempPath, hash, "/"))
	if size != toSize {
		fmt.Fprintf(w, "文件上传错误")
	}
	chunksPath := path.Join(uploadTempPath, hash, "/")
	files, _ := ioutil.ReadDir(chunksPath)
	fs, _ := os.OpenFile(path.Join(uploadPath, hash+"_"+name), os.O_CREATE|os.O_RDWR|os.O_APPEND, os.ModeAppend|os.ModePerm)
	var wg sync.WaitGroup
	wg.Add(len(files))
	for i, f := range files {
		go func(f os.FileInfo) {
			name := strings.Split(f.Name(), "-")[0] + "-" + strconv.Itoa(i)
			fileName := path.Join(chunksPath, "/"+name)
			data, _ := ioutil.ReadFile(fileName)
			fs.Write(data)
			os.RemoveAll(path.Join(chunksPath, "/"))
			defer wg.Done()
		}(f)

	}
	wg.Wait()
	m := map[string]interface{}{
		"code": 20000,
		"msg":  "上传成功",
	}
	result, _ := json.MarshalIndent(m, "", "    ")
	fmt.Fprintf(w, string(result))
	defer fs.Close()

}

// 获取整体文件夹大小
func DirSize(path string) (int64, error) {
	var size int64
	err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error {
		if !info.IsDir() {
			size += info.Size()
		}
		return err
	})
	return size, err
}
func main() {
	http.HandleFunc("/", sayhello) // set router
	http.HandleFunc("/uploadFile", uploadFile)
	http.HandleFunc("/file/chunks", chunks)
	err := http.ListenAndServe(":8080", nil) // set listen port
	if err != nil {
		log.Fatal("Error while starting GO http server on port - 8080 : ", err) //log error and exit in case of error at server boot up
	}
}

前端代码地址

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值