前端vue后端go实现大文件分片下载
- 手机
- 2025-08-03 04:51:01

先获取文件大小,然后将文件切片传输给前端,前端再按顺序组合所有切片。
vue
/** 下载数据 */ handleDownloadInstance(id, instanceName) { if (this.downloadProgressisVisible) { this.$showError('已经有文件在下载!') return } this.$showInfo('开始下载!') getFileSize(id).then((response) => { this.downloadProgressisVisible = true const fileSize = response.size this.fileSize = fileSize this.downloadPercentage = 0 this.currentSize = 0 console.log(response) // 计算分片数和每片大小 const chunkSize = 10 * 1024 * 1024 // 10 MB const totalChunks = Math.ceil(fileSize / chunkSize) // 保存所有分片的数据 const allChunks = new Array(totalChunks) const self = this let num = 0 // 下载所有分片 function downloadChunks() { for (let i = 0; i < totalChunks; i++) { const data = { start: i * chunkSize, end: (i + 1) * chunkSize - 1 } downloadInstanceChunk(id, data).then(response => { return response }) .then(chunkBlob => { // 保存分片数据 allChunks[i] = chunkBlob num += 1 // console.log('下载完成', i) // 检查是否所有分片都下载完成 if (num === totalChunks) { mergeChunks() self.$showSuccess('下载成功!') self.downloadProgressisVisible = false } self.downloadPercentage = Math.floor((num) / totalChunks * 100) self.currentSize = num * chunkSize }) .catch(error => { console.error('Error:', error) self.downloadProgressisVisible = false self.$showError('下载文件失败:' + error.data.message) }) } } // 合并所有分片 function mergeChunks() { // 创建一个 Blob 对象,包含所有分片数据 const mergedBlob = new Blob(allChunks, { type: 'application/zip' }) // 创建下载链接并模拟点击 const downloadLink = document.createElement('a') downloadLink.href = URL.createObjectURL(mergedBlob) const fileName = `${instanceName}.zip` downloadLink.download = fileName downloadLink.click() } // 调用下载分片函数 downloadChunks() }).catch(err => { console.log(err) this.$showError('下载文件失败:' + err.data.message) this.downloadProgressisVisible = false }) },go
func (handler *Handler) getFileSize(w http.ResponseWriter, r *http.Request) *httperror.HandlerError { instanceID, err := request.RetrieveNumericRouteVariableValue(r, "id") if err != nil { return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid instance identifier route variable", Err: err} } instance, err := handler.DataStore.Instance().Instance(uint(instanceID)) if err == bolterrors.ErrObjectNotFound { return &httperror.HandlerError{StatusCode: http.StatusNotFound, Message: "Unable to find a instance with the specified identifier inside the database", Err: err} } else if err != nil { return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to find a instance with the specified identifier inside the database", Err: err} } // timeStr := instance.ReportTime.Format("2006-01-02 15:04:05") // timeStr = strings.Replace(timeStr, ":", "-", -1) // timeStr = strings.Replace(timeStr, " ", "-", -1) dirPath := instance.TempPath zipPath := instance.InstanceName + ".zip" zipPath = "/home/1.zip" dirPath = "/home/ if !utils.DirExists(dirPath) { return &httperror.HandlerError{StatusCode: http.StatusNotFound, Message: "文件不存在", Err: fmt.Errorf("文件不存在")} } _, err = os.Stat(zipPath) if err != nil { err = utils.ZipDir(dirPath, zipPath, []string{".pcap"}) if err != nil { return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "压缩文件失败", Err: fmt.Errorf("压缩文件失败")} } } fileInfo, err := os.Stat(zipPath) if err != nil { return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "os.Stat 失败", Err: err} } return response.JSON(w, map[string]int64{ "size": fileInfo.Size(), }) } func (handler *Handler) downloadInstanceChunk(w http.ResponseWriter, r *http.Request) *httperror.HandlerError { instanceID, err := request.RetrieveNumericRouteVariableValue(r, "id") if err != nil { return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid instance identifier route variable", Err: err} } start, err := request.RetrieveNumericRouteVariableValue(r, "start") if err != nil { return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid instance identifier route variable", Err: err} } end, err := request.RetrieveNumericRouteVariableValue(r, "end") if err != nil { return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid instance identifier route variable", Err: err} } instance, err := handler.DataStore.Instance().Instance(uint(instanceID)) if err == bolterrors.ErrObjectNotFound { return &httperror.HandlerError{StatusCode: http.StatusNotFound, Message: "Unable to find a instance with the specified identifier inside the database", Err: err} } else if err != nil { return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to find a instance with the specified identifier inside the database", Err: err} } // timeStr := instance.ReportTime.Format("2006-01-02 15:04:05") // timeStr = strings.Replace(timeStr, ":", "-", -1) // timeStr = strings.Replace(timeStr, " ", "-", -1) dirPath := instance.TempPath zipPath := instance.InstanceName + ".zip" zipPath = "/home/1.zip" dirPath = "/home/test" if !utils.DirExists(dirPath) { return &httperror.HandlerError{StatusCode: http.StatusNotFound, Message: "文件不存在", Err: fmt.Errorf("文件不存在")} } // err = utils.ZipDir(dirPath, zipPath, []string{".pcap"}) if err != nil { return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "压缩文件失败", Err: fmt.Errorf("压缩文件失败")} } fileInfo, err := os.Stat(zipPath) if err != nil { return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "os.Stat 失败", Err: err} } // 计算最后一片的范围 if end == 0 || int64(end) > fileInfo.Size() { end = int(fileInfo.Size()) - 1 } zipFile, err := os.Open(zipPath) if err != nil { return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "文件无法打开", Err: fmt.Errorf("文件无法打开")} } defer zipFile.Close() w.Header().Set("Content-Type", "application/zip") // w.Header().Set("Content-Type", "application/octet-stream") // w.Header().Set("Content-Length", strconv.FormatInt(fileInfo.Size(), 10)) // 设置响应头部,指定传输的范围 w.Header().Set("Content-Range", "bytes "+strconv.FormatInt(int64(start), 10)+"-"+strconv.FormatInt(int64(end), 10)) w.WriteHeader(http.StatusPartialContent) // 将部分内容传输到客户端 _, err = zipFile.Seek(int64(start), 0) if err != nil { return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to seek to the specified position", Err: err} } io.CopyN(w, zipFile, int64(end)-int64(start)+1) return response.Empty(w) }前端vue后端go实现大文件分片下载由讯客互联手机栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“前端vue后端go实现大文件分片下载”