本文介绍如何将源Bucket中的文件(Object)复制到同一地域下相同或不同目标Bucket中。
注意事项
本文以华东1(杭州)外网Endpoint为例。如果您希望通过与OSS同地域的其他阿里云产品访问OSS,请使用内网Endpoint。关于OSS支持的Region与Endpoint的对应关系,请参见OSS访问域名、数据中心、开放端口。
本文以从环境变量读取访问凭证为例。如何配置访问凭证,请参见Java配置访问凭证。
本文以OSS域名新建OSSClient为例。如果您希望通过自定义域名、STS等方式新建OSSClient,请参见新建OSSClient。
拷贝文件时,您必须拥有源文件的读权限及目标Bucket的读写权限。
拷贝文件时,您需要确保源Bucket和目标Bucket均未设置合规保留策略,否则报错The object you specified is immutable.。
不支持跨地域拷贝。例如不能将华东1(杭州)地域存储空间中的文件拷贝到华北1(青岛)地域。
拷贝小文件
您可以通过copy方法在同一个Bucket或者同一个Region下的不同Bucket之间拷贝文件,文件大小不能超过1 GB。
同一个Bucket中拷贝文件
以下代码用于在同一个Bucket中拷贝文件。
const OSS = require('ali-oss'); const client = new OSS({ // yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。 region: 'yourRegion', // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。 accessKeyId: process.env.OSS_ACCESS_KEY_ID, accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET, authorizationV4: true, // 填写Bucket名称。例如examplebucket。 bucket: 'examplebucket', // 设置是否启用HTTPS。设置secure为true时,表示启用。 // secure: true }) // 拷贝同一个Bucket中的文件。 async function copySmallObjecInSameBucket() { try { // 填写拷贝后和拷贝前的文件完整路径。文件完整路径中不能包含Bucket名称。 // 设置目标文件的HTTP头和自定义目标文件的元数据。 const result = await client.copy('destexampleobject.txt', 'srcexampleobject.txt', { // 指定headers参数,设置目标文件的HTTP头。如果未指定headers参数,则目标文件与源文件的HTTP头相同,即拷贝源文件的HTTP头。 headers: { 'Cache-Control': 'no-cache', // 如果源Object的ETag值和您提供的ETag相等,则执行拷贝操作,并返回200 OK。 'if-match': '5B3C1A2E053D763E1B002CC607C5****', // 如果源Object的ETag值和您提供的ETag不相等,则执行拷贝操作,并返回200 OK。 'if-none-match': '5B3C1A2E053D763E1B002CC607C5****', // 如果指定的时间早于文件实际修改时间,则执行拷贝操作,并返回200 OK。 'if-modified-since': '2021-12-09T07:01:56.000Z', // 如果指定的时间晚于文件实际修改时间,则执行拷贝操作,并返回200 OK。 'if-unmodified-since': '2021-12-09T07:01:56.000Z', // 指定OSS创建目标Object时的访问权限,此处设置为private,表示只有Object的拥有者和授权用户有该Object的读写权限,其他用户没有权限操作该Object。 'x-oss-object-acl': 'private', // 指定Object的对象标签,可同时设置多个标签。 'x-oss-tagging': 'Tag1=1&Tag2=2', // 指定CopyObject操作时是否覆盖同名目标Object。此处设置为true,表示禁止覆盖同名Object。 'x-oss-forbid-overwrite': 'true', }, // 指定meta参数,自定义目标文件的元数据。如果未指定meta参数,目标文件与源文件的元数据相同,即拷贝源文件的元数据。 meta: { location: 'hangzhou', year: 2015, people: 'mary', }, }); console.log(result); } catch (e) { console.log(e); } } copySmallObjecInSameBucket()
同一Region下不同Bucket之间拷贝文件
以下代码用于在同一个Region下不同Bucket之间拷贝文件。
const OSS = require('ali-oss'); const client = new OSS({ // yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。 region: 'yourRegion', // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。 accessKeyId: process.env.OSS_ACCESS_KEY_ID, accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET, authorizationV4: true, // 填写目标Bucket名称。 bucket: 'destexamplebucket', }); async function copySmallObjectBetweenBuckets() { try { // 分别填写拷贝后的文件名称destobject.txt、拷贝前的文件名称srcobject.txt以及拷贝前文件所属的Bucket名称。 const result = await client.copy('destobject.txt', 'srcobject.txt', 'srcbucket', { // 指定headers参数,设置目标文件的HTTP头。如果未指定headers参数,则目标文件与源文件的HTTP头相同,即拷贝源文件的HTTP头。 headers: { 'Cache-Control': 'no-cache', }, // 指定meta参数,自定义目标文件的元数据。如果未指定meta参数,目标文件与源文件的元数据相同,即拷贝源文件的元数据。 meta: { location: 'hangzhou', year: 2015, people: 'mary', }, }); console.log(result); } catch (e) { console.log(e); } } copySmallObjectBetweenBuckets()
拷贝大文件
对于大于1 GB文件,您可以使用multipartUploadCopy
方法进行分片拷贝。
以下代码用于在同一个Region下不同Bucket之间拷贝文件。
const OSS = require("ali-oss");
const client = new OSS({
// yourregion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
region: 'yourregion',
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
accessKeyId: process.env.OSS_ACCESS_KEY_ID,
accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
authorizationV4: true,
// 填写目标Bucket名称。
bucket: "destexamplebucket",
});
async function copyLargeObjectBetweenDifferentBuckets() {
try {
const copyheaders = {
// 如果源Object的ETag值和用户提供的ETag相等,则执行拷贝操作;否则返回412 HTTP错误码(预处理失败)。
"x-oss-copy-source-if-match": "5B3C1A2E053D763E1B002CC607C5****",
// 如果传入的ETag值和Object的ETag不匹配,则执行拷贝操作,并返回200 OK;否则返回304 Not Modified。
"x-oss-copy-source-if-none-match": "5B3C1A2E053D763E1B002CC607C5****",
// 如果参数传入的时间等于或者晚于文件实际修改时间,则执行拷贝操作,并返回200 OK;否则返回412 precondition failed错误。
"x-oss-copy-source-if-unmodified-since": "2022-12-09T07:01:56.000Z",
// 如果指定的时间早于实际修改时间,则执行拷贝操作,并返回200 OK;否则返回304 not modified。
"x-oss-copy-source-if-modified-since": "2022-12-09T07:01:56.000Z",
};
const headers = {
// 指定该Object被下载时的网页的缓存行为。
"Cache-Control": "no-cache",
// 指定该Object被下载时的名称。
"Content-Disposition": "somename",
// 指定该Object被下载时的内容编码格式。
"Content-Encoding": "utf-8",
// 指定过期时间,单位为毫秒。
Expires: "1000",
};
let savedCpt;
// 填写拷贝后的文件完整路径,文件完整路径中不能包含Bucket名称,例如destexampleobject1.txt。
const r1 = await client.multipartUploadCopy("destexampleobject1.txt", {
// 填写拷贝前的文件完整路径,文件完整路径中不能包含Bucket名称,例如srcexampleobject.txt。
sourceKey: "srcexampleobject.txt",
// 填写源Bucket名称,例如sourcebucket。
sourceBucketName: "sourcebucket",
copyheaders: copyheaders,
});
console.log(r1);
// 填写拷贝后的文件完整路径,文件完整路径中不能包含Bucket名称,例如destexampleobject2.txt。
const r2 = await client.multipartUploadCopy("destexampleobject2.txt", {
// 填写拷贝前的文件完整路径,文件完整路径中不能包含Bucket名称,例如srcexampleobject.txt。
sourceKey: "srcexampleobject.txt",
// 填写源Bucket名称,例如sourcebucket。
sourceBucketName: "sourcebucket",
}, {
// 设置并行上传的分片数量。
parallel: 4,
// 设置分片大小。
partSize: 1024 * 1024,
progress: function (p, cpt, res) {
console.log(p);
savedCpt = cpt;
console.log(cpt);
console.log(res.headers["x-oss-request-id"]);
},
headers: headers,
copyheaders: copyheaders,
});
console.log(r2);
// 填写拷贝后的文件完整路径,文件完整路径中不能包含Bucket名称,例如destexampleobject3.txt。
const r3 = await client.multipartUploadCopy("destexampleobject3.txt", {
// 填写拷贝前的文件完整路径,文件完整路径中不能包含Bucket名称,例如srcexampleobject.txt。
sourceKey: "srcexampleobject.txt",
// 填写源Bucket名称,例如sourcebucket。
sourceBucketName: "sourcebucket",
}, {
checkpoint: savedCpt,
progress: function (p, cpt, res) {
console.log(p);
console.log(cpt);
console.log(res.headers["x-oss-request-id"]);
},
});
console.log(r3);
} catch (e) {
console.log(e);
}
}
copyLargeObjectBetweenDifferentBuckets()
相关文档
拷贝小文件
关于拷贝小文件的完整示例代码,请参见GitHub示例。
关于拷贝小文件的API接口说明,请参见CopyObject。
拷贝大文件
关于拷贝大文件的完整示例代码,请参见GitHub示例。
关于拷贝大文件的API接口说明,请参见UploadPartCopy。