Skip to content

Commit aa25dd4

Browse files
committed
Merge pull request #562 from aws/s3-0b-upload
Fix `AWS.S3.ManagedUpload` to upload zero byte bodies.
2 parents edd33fe + 1fd12b2 commit aa25dd4

File tree

2 files changed

+31
-7
lines changed

2 files changed

+31
-7
lines changed

lib/s3/managed_upload.js

+8-7
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,6 @@ AWS.S3.ManagedUpload = AWS.util.inherit({
168168
});
169169
}
170170
}
171-
172171
if (runFill) self.fillQueue.call(self);
173172
},
174173

@@ -204,7 +203,9 @@ AWS.S3.ManagedUpload = AWS.util.inherit({
204203
validateBody: function validateBody() {
205204
var self = this;
206205
self.body = self.service.config.params.Body;
207-
if (!self.body) throw new Error('params.Body is required');
206+
if (self.body === null || self.body === undefined) {
207+
throw new Error('params.Body is required');
208+
}
208209
if (typeof self.body === 'string') {
209210
self.body = new AWS.util.Buffer(self.body);
210211
}
@@ -239,7 +240,7 @@ AWS.S3.ManagedUpload = AWS.util.inherit({
239240
} catch (e) { }
240241

241242
// try to adjust partSize if we know payload length
242-
if (self.totalBytes) {
243+
if (typeof self.totalBytes === 'number') {
243244
var newPartSize = Math.ceil(self.totalBytes / self.maxTotalParts);
244245
if (newPartSize > self.partSize) self.partSize = newPartSize;
245246
} else {
@@ -323,7 +324,8 @@ AWS.S3.ManagedUpload = AWS.util.inherit({
323324
fillBuffer: function fillBuffer() {
324325
var self = this;
325326
var bodyLen = byteLength(self.body);
326-
while (self.activeParts < self.queueSize && self.partPos < bodyLen) {
327+
while (!self.isDoneChunking && self.activeParts < self.queueSize
328+
&& self.partPos <= bodyLen) {
327329
var endPos = Math.min(self.partPos + self.partSize, bodyLen);
328330
var buf = self.sliceFn.call(self.body, self.partPos, endPos);
329331
self.partPos += self.partSize;
@@ -349,20 +351,19 @@ AWS.S3.ManagedUpload = AWS.util.inherit({
349351
self.partBuffer = AWS.util.Buffer.concat([self.partBuffer, buf]);
350352
self.totalChunkedBytes += buf.length;
351353
}
352-
353354
if (self.partBuffer.length >= self.partSize) {
354355
self.nextChunk(self.partBuffer.slice(0, self.partSize));
355356
self.partBuffer = self.partBuffer.slice(self.partSize);
356357
} else if (self.isDoneChunking) {
357358
self.totalBytes = self.totalChunkedBytes;
358-
if (self.partBuffer.length > 0) {
359+
if (self.partBuffer.length >= 0) {
359360
self.numParts++;
360361
self.nextChunk(self.partBuffer);
361362
}
362363
self.partBuffer = new AWS.util.Buffer(0);
363364
}
364365

365-
self.body.read(0);
366+
if (!self.isDoneChunking) self.body.read(0);
366367
},
367368

368369
/**

test/s3/managed_upload.spec.coffee

+23
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ body = (size) ->
77
catch e
88
return new AWS.util.Buffer(size)
99

10+
zerobody = body(0)
1011
smallbody = body(5)
1112
bigbody = body(36)
1213

@@ -53,6 +54,18 @@ describe 'AWS.S3.ManagedUpload', ->
5354
it 'uses a default service object if none provided', ->
5455
expect(-> new AWS.S3.ManagedUpload()).to.throw('params.Body is required')
5556

57+
it 'uploads a zero byte body', ->
58+
reqs = helpers.mockResponses [
59+
data: ETag: 'ETAG'
60+
]
61+
62+
send Body: zerobody, ContentEncoding: 'encoding', ->
63+
expect(err).not.to.exist
64+
expect(data.ETag).to.equal('ETAG')
65+
expect(data.Location).to.equal('https://bucket.s3.mock-region.amazonaws.com/key')
66+
expect(helpers.operationsForRequests(reqs)).to.eql ['s3.putObject']
67+
expect(reqs[0].params.ContentEncoding).to.equal('encoding')
68+
5669
it 'uploads a single part if size is less than min multipart size', ->
5770
reqs = helpers.mockResponses [
5871
data: ETag: 'ETAG'
@@ -226,6 +239,16 @@ describe 'AWS.S3.ManagedUpload', ->
226239

227240
if AWS.util.isNode()
228241
describe 'streaming', ->
242+
243+
it 'sends a zero length stream in a single putObject', (done) ->
244+
stream = AWS.util.buffer.toStream(zerobody)
245+
reqs = helpers.mockResponses [data: ETag: 'ETAG']
246+
upload = new AWS.S3.ManagedUpload params: { Body: stream }
247+
upload.send ->
248+
expect(helpers.operationsForRequests(reqs)).to.eql ['s3.putObject']
249+
expect(err).not.to.exist
250+
done()
251+
229252
it 'sends a small stream in a single putObject', (done) ->
230253
stream = AWS.util.buffer.toStream(smallbody)
231254
reqs = helpers.mockResponses [data: ETag: 'ETAG']

0 commit comments

Comments
 (0)