Appcube大文件 分段上传(一)
【摘要】 Appcube大文件 分段上传(一)
Appcube 中ABC平台接口内容体最大允许5M左右,
对于大文件上传,有两种方式
1.运维解除平台请求体大小限制,对于Ngnix转发的文件上传接口,需要在ngnix中配置传输最大内容体,不然ngnix会使用默认值。
2.针对大文件做分段上传,同步开启多个异步任务切片上传,耗时会大大缩短。
参考资料地址:https://appcube.cn-north-4.huaweicloud.cn/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.cn/u-route/baas/sys/v1.1/connectors/objectstorageproxy/' + storageName + '/viewobject?object=' + filePath;
// 'https://studio.e.huawei.cn/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.cn/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)