Skip to content

Commit 02d59da

Browse files
authored
feat: image processing (#744)
close #676
1 parent 67275bd commit 02d59da

File tree

7 files changed

+146
-0
lines changed

7 files changed

+146
-0
lines changed

README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2673,6 +2673,33 @@ object:
26732673
- status {Number} response status
26742674
- res {Object} response info
26752675
2676+
### .processObjectSave(sourceObject, targetObject, process[, targetBucket])
2677+
2678+
Persistency indicates that images are asynchronously stored in the specified Bucket
2679+
2680+
parameters:
2681+
2682+
- sourceObject {String} source object name
2683+
- targetObject {String} target object name
2684+
- process {String} process string
2685+
- [targetBucket] {String} target bucket
2686+
2687+
Success will return the channel information.
2688+
2689+
object:
2690+
2691+
- status {Number} response status
2692+
- res {Object} response info
2693+
2694+
2695+
```js
2696+
const sourceObject = 'a.png'
2697+
const targetObject = 'b.png'
2698+
const process = 'image/watermark,text_aGVsbG8g5Zu+54mH5pyN5Yqh77yB,color_ff6a00'
2699+
2700+
await this.store.processObjectSave(sourceObject, targetObject, process);
2701+
```
2702+
26762703
## RTMP Operations
26772704
26782705
All operations function is [async], except `getRtmpUrl`.

lib/browser/object.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ merge(proto, require('../common/object/copyObject'));
278278
merge(proto, require('../common/object/getObjectTagging'));
279279
merge(proto, require('../common/object/putObjectTagging'));
280280
merge(proto, require('../common/object/deleteObjectTagging'));
281+
merge(proto, require('../common/image'));
281282

282283
proto.putMeta = async function putMeta(name, meta, options) {
283284
const copyResult = await this.copy(name, name, {

lib/client.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ const proto = Client.prototype;
7373
*/
7474
merge(proto, require('./common/object'));
7575
merge(proto, require('./object'));
76+
merge(proto, require('./common/image'));
7677
/**
7778
* Bucket operations
7879
*/

lib/common/image/index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const merge = require('merge-descriptors');
2+
3+
const proto = exports;
4+
5+
merge(proto, require('./processObjectSave'));

lib/common/image/processObjectSave.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/* eslint-disable no-use-before-define */
2+
const querystring = require('querystring');
3+
const { Base64: { encode: str2Base64 } } = require('js-base64');
4+
5+
const proto = exports;
6+
7+
proto.processObjectSave = async function processObjectSave(sourceObject, targetObject, process, targetBucket) {
8+
checkArgs(sourceObject, 'sourceObject');
9+
checkArgs(targetObject, 'targetObject');
10+
checkArgs(process, 'process');
11+
targetObject = this._objectName(targetObject);
12+
if (targetBucket) {
13+
this._checkBucketName(targetBucket);
14+
}
15+
16+
const params = this._objectRequestParams('POST', sourceObject, {
17+
subres: 'x-oss-process'
18+
});
19+
20+
const bucketParam = targetBucket ? `,b_${str2Base64(targetBucket)}` : '';
21+
targetObject = str2Base64(targetObject);
22+
23+
const content = {
24+
'x-oss-process': `${process}|sys/saveas,o_${targetObject}${bucketParam}`
25+
};
26+
params.content = querystring.stringify(content);
27+
28+
const result = await this.request(params);
29+
return {
30+
res: result.res,
31+
status: result.res.status
32+
};
33+
};
34+
35+
function checkArgs(name, key) {
36+
if (!name) {
37+
throw new Error(`${key} is required`);
38+
}
39+
if (typeof name !== 'string') {
40+
throw new Error(`${key} must be String`);
41+
}
42+
}

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@
120120
"get-ready": "^1.0.0",
121121
"humanize-ms": "^1.2.0",
122122
"is-type-of": "^1.0.0",
123+
"js-base64": "^2.5.2",
123124
"jstoxml": "^0.2.3",
124125
"merge-descriptors": "^1.0.1",
125126
"mime": "^1.3.4",

test/node/object.test.js

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,75 @@ describe('test/object.test.js', () => {
161161
});
162162
});
163163

164+
describe('processObjectSave()', () => {
165+
const name = 'sourceObject.png';
166+
before(async () => {
167+
const imagepath = path.join(__dirname, 'nodejs-1024x768.png');
168+
await store.putStream(name, fs.createReadStream(imagepath), {
169+
mime: 'image/png'
170+
});
171+
});
172+
const target = `processObject_target${Date.now()}.jpg`;
173+
it('should process image', async () => {
174+
try {
175+
const result = await store.processObjectSave(name, target, 'image/watermark,text_aGVsbG8g5Zu+54mH5pyN5Yqh77yB,color_ff6a00,');
176+
assert.strictEqual(result.res.status, 200);
177+
} catch (error) {
178+
assert(false, error);
179+
}
180+
});
181+
it('should process image with targetBucket', async () => {
182+
try {
183+
const result = await store.processObjectSave(name, target, 'image/watermark,text_aGVsbG8g5Zu+54mH5pyN5Yqh77yB,color_ff6a00,', archvieBucket);
184+
assert.strictEqual(result.res.status, 200);
185+
} catch (error) {
186+
assert(false, error);
187+
}
188+
});
189+
it('should throw error when sourceObjectName is invalid', async () => {
190+
try {
191+
await store.processObjectSave('', target, 'image/watermark,text_aGVsbG8g5Zu+54mH5pyN5Yqh77yB,color_ff6a00,');
192+
assert(false);
193+
} catch (error) {
194+
assert(error.message.includes('required'));
195+
}
196+
try {
197+
await store.processObjectSave({}, target, 'image/watermark,text_aGVsbG8g5Zu+54mH5pyN5Yqh77yB,color_ff6a00,');
198+
assert(false);
199+
} catch (error) {
200+
assert(error.message.includes('must be String'));
201+
}
202+
});
203+
it('should throw error when targetObjectName is invalid', async () => {
204+
try {
205+
await store.processObjectSave(name, '', 'image/watermark,text_aGVsbG8g5Zu+54mH5pyN5Yqh77yB,color_ff6a00,');
206+
assert(false);
207+
} catch (error) {
208+
assert(error.message.includes('required'));
209+
}
210+
try {
211+
await store.processObjectSave(name, {}, 'image/watermark,text_aGVsbG8g5Zu+54mH5pyN5Yqh77yB,color_ff6a00,');
212+
assert(false);
213+
} catch (error) {
214+
assert(error.message.includes('must be String'));
215+
}
216+
});
217+
it('should throw error when process is invalid', async () => {
218+
try {
219+
await store.processObjectSave(name, target, '');
220+
assert(false);
221+
} catch (error) {
222+
assert(error.message.includes('required'));
223+
}
224+
try {
225+
await store.processObjectSave(name, target, {});
226+
assert(false);
227+
} catch (error) {
228+
assert(error.message.includes('must be String'));
229+
}
230+
});
231+
});
232+
164233
describe('getObjectUrl()', () => {
165234
it('should return object url', () => {
166235
let name = 'test.js';

0 commit comments

Comments
 (0)