diff --git a/lib/common/multipart.js b/lib/common/multipart.js index c1ab0ad53..51742faf2 100644 --- a/lib/common/multipart.js +++ b/lib/common/multipart.js @@ -1,6 +1,7 @@ const copy = require('copy-to'); const callback = require('./callback'); +const deepCopy = require('./utils/deepCopy'); const proto = exports; @@ -181,8 +182,9 @@ proto.completeMultipartUpload = async function completeMultipartUpload(name, upl xml += ''; options = options || {}; - const opt = {}; - copy(options).to(opt); + let opt = {}; + opt = deepCopy(options); + if (opt.headers) delete opt.headers['x-oss-server-side-encryption']; opt.subres = { uploadId }; const params = this._objectRequestParams('POST', name, opt); diff --git a/lib/common/utils/deepCopy.js b/lib/common/utils/deepCopy.js new file mode 100644 index 000000000..c346bd066 --- /dev/null +++ b/lib/common/utils/deepCopy.js @@ -0,0 +1,20 @@ +module.exports = function deepCopy(obj, cache = []) { + if (obj === null || typeof obj !== 'object') { + return obj; + } + const hit = cache.filter(c => c.original === obj)[0]; + if (hit) { + return hit.copy; + } + const copy = Array.isArray(obj) ? [] : {}; + cache.push({ + original: obj, + copy + }); + + Object.keys(obj).forEach((key) => { + copy[key] = deepCopy(obj[key], cache); + }); + + return copy; +}; diff --git a/test/browser/browser.test.js b/test/browser/browser.test.js index bb1c3314c..5f4cec821 100644 --- a/test/browser/browser.test.js +++ b/test/browser/browser.test.js @@ -960,6 +960,18 @@ describe('browser', () => { assert.equal(result.res.headers['x-oss-server-side-encryption'], 'AES256'); }); + it('should multipartUpload with x-oss-server-side-encryption', async () => { + const name = 'multipart-x-oss-server-side-encryption'; + const fileContent = Array(1034 * 1024).fill('a').join(''); + const fileName = new File([fileContent], 'multipart-upload-kms'); + const result = await store.multipartUpload(name, fileName, { + headers: { + 'x-oss-server-side-encryption': 'KMS' + } + }); + assert.equal(result.res.headers['x-oss-server-side-encryption'], 'KMS'); + }); + it('should fallback to putStream when file size is smaller than 100KB', async () => { const file = new File(['multipart-fallback-test'], 'multipart-fallback'); const name = `${prefix}multipart/fallback`; diff --git a/test/node/multipart.test.js b/test/node/multipart.test.js index d51b9ee0d..8117abcda 100644 --- a/test/node/multipart.test.js +++ b/test/node/multipart.test.js @@ -157,6 +157,20 @@ describe('test/multipart.test.js', () => { assert.equal(result.res.headers['x-oss-server-side-encryption'], 'AES256'); }); + it('should multipartUpload with x-oss-server-side-encryption', async () => { + const name = 'multipart-x-oss-server-side-encryption'; + const fileName = await utils.createTempFile( + 'multipart-fallback', + 1003 * 1020 + ); + const result = await store.multipartUpload(name, fileName, { + headers: { + 'x-oss-server-side-encryption': 'KMS' + } + }); + assert.equal(result.res.headers['x-oss-server-side-encryption'], 'KMS'); + }); + it('should fallback to putStream when file size is smaller than 100KB', async () => { const fileName = await utils.createTempFile('multipart-fallback', (100 * 1024) - 1); const name = `${prefix}multipart/fallback`;