|                                                                          |  | const { checkBucketName: _checkBucketName } = require('../utils/checkBucketName');
const proto = exports;
const REPLACE_HEDERS = [  'content-type',  'content-encoding',  'content-language',  'content-disposition',  'cache-control',  'expires'];
proto.copy = async function copy(name, sourceName, bucketName, options) {  if (typeof bucketName === 'object') {    options = bucketName; // 兼容旧版本,旧版本第三个参数为options
  }  options = options || {};  options.headers = options.headers || {};
  Object.keys(options.headers).forEach(key => {    options.headers[`x-oss-copy-source-${key.toLowerCase()}`] = options.headers[key];  });  if (options.meta || Object.keys(options.headers).find(_ => REPLACE_HEDERS.includes(_.toLowerCase()))) {    options.headers['x-oss-metadata-directive'] = 'REPLACE';  }  this._convertMetaToHeaders(options.meta, options.headers);
  sourceName = this._getSourceName(sourceName, bucketName);
  if (options.versionId) {    sourceName = `${sourceName}?versionId=${options.versionId}`;  }
  options.headers['x-oss-copy-source'] = sourceName;
  const params = this._objectRequestParams('PUT', name, options);  params.xmlResponse = true;  params.successStatuses = [200, 304];
  const result = await this.request(params);
  let { data } = result;  if (data) {    data = {      etag: data.ETag,      lastModified: data.LastModified    };  }
  return {    data,    res: result.res  };};
// todo delete
proto._getSourceName = function _getSourceName(sourceName, bucketName) {  if (typeof bucketName === 'string') {    sourceName = this._objectName(sourceName);  } else if (sourceName[0] !== '/') {    bucketName = this.options.bucket;  } else {    bucketName = sourceName.replace(/\/(.+?)(\/.*)/, '$1');    sourceName = sourceName.replace(/(\/.+?\/)(.*)/, '$2');  }
  _checkBucketName(bucketName);
  sourceName = encodeURIComponent(sourceName);
  sourceName = `/${bucketName}/${sourceName}`;  return sourceName;};
 |