前端代码:

文件上传按钮及样式

<template>
    <div>
        <el-button class="file-box" text>
            <input type="file" multiple class="file-btn" 
            required @change="handleFileChange" />上传
        </el-button>
    </div>
</template>
<style>
.file-box {
    display: inline-block;
    position: relative;
    overflow: hidden;
    color: rgb(252, 113, 0);
    background-color: rgb(255, 255, 255);
}

.file-btn {
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    outline: none;
    filter: alpha(opacity=0);
    -moz-opacity: 0;
    -khtml-opacity: 0;
    opacity: 0;
}
</style>

添加上传方法,生成uploadid:

        //生成uploadid
        async handleFileChange(e) {
            this.file = e.target.files[0];
            const data = {
                bucket_name: this.bucket_name, //桶名
                object_name: this.file.name  //文件名
            };
            //upload_addr后端地址
            let res = await func.post(this.upload_addr 
            + '/new_multipart_upload', data);
            this.upload_id = res.data.data;
            //初始化上传进度,upload_progress是一个map
            this.upload_progress.set(this.upload_id, 0);
            this.uploadFile();
        },

分片,生成分片上传URL:

        async uploadFile() {
            if (!this.file) {
                alert('请选择文件');
                return;
            }
            const totalChunks = Math.ceil(this.file.size / this.chunkSize);
            for (let chunk = 0; chunk < totalChunks; chunk++) {
                const start = chunk * this.chunkSize;
                const end = Math.min(this.file.size, start + this.chunkSize);
                const chunkFile = this.file.slice(start, end);

                let part_num = chunk + 1;
                const data = {
                    bucket_name: this.bucket_name,
                    object_name: this.file.name,
                    upload_id: this.upload_id,
                    part_num: part_num
                };
                // 为每个分片生成上传URL
                let res = await func.post(this.upload_addr + '/presign', 
                data);
                let url = res.data.data;
                try {
                    await this.uploadChunk(chunkFile, url, 
                part_num, totalChunks);
                } catch (error) {
                    console.error(error);
                }
            }
        },

上传分片:

        async uploadChunk(file, url, part_num, totalChunks) {
            fetch(url, {
                method: 'PUT',
                body: file
            })
                .then((response) => {
                    console.log(`${part_num} 上传成功`, response);
                    
                    let sum = this.upload_progress.get(this.upload_id) + 1;
                    this.upload_progress.set(this.upload_id, sum);
                    console.log("sum: " + sum);
                    if (sum == totalChunks) {
                        this.complete_upload();
                    }
                })
                .catch((error) => {
                    console.error(`${part_num} 上传失败`, error);
                });
        },

合并分片:

        async complete_upload() {
            const data = {
                bucket_name: this.bucket_name,
                object_name: this.file.name,
                upload_id: this.upload_id,
            };
            let res = await func.post(this.upload_addr + '/complete_upload', 
            data);
        }

后端代码:

mux.Handle("/new_multipart_upload",
middleware.Cors(http.HandlerFunc(common.NewMultipartUpload)))
mux.Handle("/presign", 
middleware.Cors(http.HandlerFunc(common.Presign)))
mux.Handle("/complete_upload",
middleware.Cors(http.HandlerFunc(common.CompleteMultipartUpload)))
//··························
var (
	client        *minio.Client
	core          *minio.Core

)

func InitMinio() {
	client = InitMinioClient()
	core = &minio.Core{
		Client: client,
	}
}

func InitMinioClient() *minio.Client {
	// 基本的配置信息
	endpoint := config.ConfData.Minio.Address + ":" + strconv.Itoa(config.ConfData.Minio.Port)
	accessKeyID := config.ConfData.Minio.AccessKeyID
	secretAccessKey := config.ConfData.Minio.SecretAccessKey
	minioClient, err := minio.New(endpoint, accessKeyID, secretAccessKey, false)
	if err != nil {
		logx.Fatalf("初始化MinioClient错误:%s", err.Error())
	} else {
		logx.Info("Minio api start")
	}

	return minioClient
}



// 获取上传id
func NewMultipartUpload(w http.ResponseWriter, r *http.Request) {
	bucketname := r.PostFormValue("bucket_name")
	objectname := r.PostFormValue("object_name")
	id, err := core.NewMultipartUpload(bucketname, objectname, minio.PutObjectOptions{})
	if err != nil {
		logx.Errorf("NewMultipartUpload error: %v", err)
		httpx.OkJson(w, ResponseData{
			Code: CodeInternalServerError,
			Msg:  "failed to create multipart upload:" + err.Error(),
		})
		return
	}
	httpx.OkJson(w, ResponseData{
		Code: CodeSuccess,
		Msg:  "success",
		Data: id,
	})
}

// 获取上传链接
func Presign(w http.ResponseWriter, r *http.Request) {
	bucketname := r.PostFormValue("bucket_name")
	objectname := r.PostFormValue("object_name")
	uploadID := r.PostFormValue("upload_id")
	partNum := r.PostFormValue("part_num")
    //这里设置为PUT
	url, err := client.Presign("PUT", bucketname, objectname, 100*time.Second, url.Values{
		"uploadId":   []string{uploadID},
		"partNumber": []string{partNum},
	})
	if err != nil {
		logx.Error(err)
	}
	httpx.OkJson(w, ResponseData{
		Code: CodeSuccess,
		Msg:  "success",
		Data: url.String(),
	})
}

// 合并分片
func CompleteMultipartUpload(w http.ResponseWriter, r *http.Request) {
	bucketname := r.PostFormValue("bucket_name")
	objectname := r.PostFormValue("object_name")
	upload_id := r.PostFormValue("upload_id")

	parts, err := core.ListObjectParts(bucketname, objectname, upload_id, 0, 0)
	if err != nil {
		logx.Error(err)
	}

	part_list := make([]minio.CompletePart, 0)
	for _, v := range parts.ObjectParts {
		item := minio.CompletePart{
			PartNumber: v.PartNumber,
			ETag:       v.ETag,
		}
		part_list = append(part_list, item)
	}

	res, err := core.CompleteMultipartUpload(bucketname, 
objectname, upload_id,part_list)
	if err != nil {
		logx.Error(err)
	}
	logx.Info(res)
	httpx.OkJson(w, ResponseData{
		Code: CodeSuccess,
		Msg:  "success",
		Data: res,
	})
}

GitHub 加速计划 / vu / vue
207.54 K
33.66 K
下载
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
最近提交(Master分支:2 个月前 )
73486cb5 * chore: fix link broken Signed-off-by: snoppy <michaleli@foxmail.com> * Update packages/template-compiler/README.md [skip ci] --------- Signed-off-by: snoppy <michaleli@foxmail.com> Co-authored-by: Eduardo San Martin Morote <posva@users.noreply.github.com> 4 个月前
e428d891 Updated Browser Compatibility reference. The previous currently returns HTTP 404. 5 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐