Appcube大文件 分段上传(一)

举报
XH-小蝌蚪 发表于 2023/05/11 14:39:47 2023/05/11
【摘要】 Appcube大文件 分段上传(一)

Appcube   中ABC平台接口内容体最大允许5M左右,

对于大文件上传,有两种方式

1.运维解除平台请求体大小限制,对于Ngnix转发的文件上传接口,需要在ngnix中配置传输最大内容体,不然ngnix会使用默认值。

2.针对大文件做分段上传,同步开启多个异步任务切片上传,耗时会大大缩短。

参考资料地址:https://appcube.cn-north-4.huaweicloud.com/u-route/baas/doc/blog/#/script/objectstorage_multipart_upload

方式一:

1.创建脚本upload1,初始化分段上传任务。

import * as obs from 'objectstorage';

// 对象名作为入参
export class Input {
    @action.param({ type: "String", required: true, description: "对象名" })
    object: string;
}

export class Output {
    @action.param({ type: "String", required: true })
    uploadId: string;
}

export class Calculator {
    @action.method({ input: "Input", output: "Output", description: "do a operation" })
    run(input: Input): Output {
        // 此处可添加文件名等限制, 这里仅作为样例,仅用于展示分段上传的主流程
        let cli = obs.newClient(obs.StoreType.PROXY, "SmartCampus__FileOperator");
        let uploadId = cli.createMultipartUpload(input.object, { acl: "public-read" });
        let output = new Output();
        output.uploadId = uploadId
        return output;
    }
}

2.创建脚本upload2,分段上传脚本

import * as http from 'http';
import * as obs from 'objectstorage';
export class Input {
    @action.param({ type: "String", required: true, description: "对象名" })
    object: string;
    @action.param({ type: "String", required: true, description: "上传 id" })
    uploadId: string;
    @action.param({ type: "Number", required: true, description: "分片" })
    partNum: number;
    @action.param({ type: "Any", required: true, description: "分片数据" })
    $data: http.FormData;;
}

export class Output {
    @action.param({ type: "Any", required: true })
    part: obs.CompletedPart
}

export class Calculator {
    @action.method({ input: "Input", output: "Output", description: "do a operation" })
    run(input: Input): Output {
        let cli = obs.newClient(obs.StoreType.PROXY, "SmartCampus__FileOperator");
        let cp = cli.uploadPart(input.object, input.uploadId, input.partNum, input.$data.data)
  
        let output = new Output();
        output.part = cp;
        return output;
    }
}

2.创建脚本upload3,合并分段上传任务,返回文件地址。

// Here's your code.
import * as obs from 'objectstorage';

export class Input {
    @action.param({ type: "String", required: true, description: "对象名" })
    object: string;
    @action.param({ type: "String", required: true, description: "上传 id" })
    uploadId: string;
    @action.param({ type: "Any", required: true, description: "分片数据" })
    completeParts: obs.CompletedPart[];
}

export class Output {
    @action.param({ type: "String", required: true, description: "访问地址" })
    endpoint: string;
}

export class Calculator {
    @action.method({ input: "Input", output: "Output", description: "do a operation" })
    run(input: Input): Output {
        let cli = obs.newClient(obs.StoreType.PROXY, "SmartCampus__FileOperator");
        // 调用 completeUpload 完成最终文件的合并,成功调用则表示文件已经上传成功
        // 'https://studio.e.huawei.com/u-route/baas/sys/v1.1/connectors/objectstorageproxy/' + storageName + '/viewobject?object=' + filePath;
        // 'https://studio.e.huawei.com/u-route/baas/sys/v1.1/connectors/objectstorageproxy/SmartCampus__FileOperator/viewobject?object=111.mp4'  { async: true }
        cli.completeUpload(input.object, input.uploadId, input.completeParts, { async: true });
        let output = new Output();
        // output.endpoint = cli.getEndpoint() + input.object;
        output.endpoint = "https://studio.e.huawei.com/u-route/baas/sys/v1.1/connectors/objectstorageproxy/SmartCampus__FileOperator/viewobject?object=" + input.object;
        return output;
    }
}

前端代码部分

     //自定义请求
                    httpResquet() {
                        let size = this.file.size / 1024 / 1024
                        console.log(size, '文件大小')
                            // 限制上传文件的大小以及格式
                        console.log(this.file);
                        let f = this.file.name;
                        // 初始化任务
                        this.upload1(f);
                    },
                    // 切片函数切成5M上传
                    createFileChunk(file, size = SIZE) {
                        const fileChunkList = [];
                        let cur = 0;
                        while (cur < file.size) {
                            fileChunkList.push({ file: file.slice(cur, cur + size) });
                            cur += size;
                        }
                        return fileChunkList;
                    },
                    // 创建分段上传任务
                    upload1(e) {
                        let body = {
                            "object": e
                        }
                        fetch(
                                `/service/Ycrl__csgn/0.1.0/upload1`, {
                                    method: "POST",
                                    headers: {
                                        "Content-Type": "application/json;charset=utf-8",
                                    },
                                    body: JSON.stringify(body)
                                },
                            )
                            .then((resp) => resp.json()).then(res => {
                                // 获取文件标识
                                this.fileID = res.result.uploadId;
                                this.upload2();

                            })
                    },
                    //分段上传接口,并发多个接口
                    async upload2() {
                        console.log(this.file, 'this.file ----->')
                        this.fileArray = this.createFileChunk(this.file, 4 * 1024 * 1024)
                        console.log(this.fileArray, '222222')
                            // ! TODO  并发请求文件
                        const jsons = this.fileArray
                            .map((v, i) => {
                                const formData = new FormData();
                                formData.append('$data', v.file);

                                let url = `/service/Ycrl__csgn/0.1.0/upload2?object=${this.file.name}&uploadId=${this.fileID}&partNum=${i + 1}`
                                return { formData, url };
                            })
                            .map(v => fetch(v.url, { method: "POST", body: v.formData }).then(res => res.json()))
                        const foo = await Promise.all(jsons)
                        console.log(foo, 'foo----》')
                        this.upload3(foo)

                    },
                    //合并分段上传任务,得到文件地址
                    upload3(e) {
                        // console.log(this.reArray, 'this.reArray')
                        // e = this.reArray
                        let arr = e.map(v => {
                            return (v.result.part);
                        })
                        console.log(arr, 'arr')

                        let body = {
                            "completeParts": arr,
                            "object": this.file.name,
                            "uploadId": this.fileID
                        }
                        console.log(body, 'body')

                        fetch(
                                `	
                            /service/Ycrl__csgn/0.1.0/upload3`, {
                                    method: "POST",
                                    headers: {
                                        "Content-Type": "application/json;charset=utf-8",
                                    },
                                    body: JSON.stringify(body)
                                },
                            )
                            .then((resp) => resp.json()).then(res => {
                   //得到文件地址res

                            })

                    },

需要注意的事扥段上传接口请求格式如下

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。