2017-05-23 27 views
5

Tôi đang cố gắng sử dụng phương pháp upload từ s3 sử dụng một ReadableStream từ các module fs.Javascript AWS SDK S3 phương pháp tải lên với dòng Body tạo tập tin rỗng

Các documentation nói rằng một ReadableStream có thể được sử dụng tại Body param:

Body - (Buffer, Typed Array, Blob, String, ReadableStream) dữ liệu Object.

Ngoài ra upload mô tả phương pháp là:

cập nhật một cách tùy tiện có kích thước bộ đệm, blob, hoặc suối, sử dụng xử lý đồng thời thông minh của các bộ phận nếu tải trọng đủ lớn.

Ngoài ra, tại đây: Upload pdf generated to AWS S3 using nodejs aws sdk @shivendra cho biết anh ấy có thể sử dụng ReadableStream và hoạt động.

Đây là mã của tôi:

const fs = require('fs') 
const S3 = require('aws-sdk/clients/s3') 

const s3 = new S3() 

const send = async() => { 
    const rs = fs.createReadStream('/home/osman/Downloads/input.txt') 
    rs.on('open',() => { 
    console.log('OPEN') 
    }) 
    rs.on('end',() => { 
    console.log('END') 
    }) 
    rs.on('close',() => { 
    console.log('CLOSE') 
    }) 
    rs.on('data', (chunk) => { 
    console.log('DATA: ', chunk) 
    }) 

    console.log('START UPLOAD') 

    const response = await s3.upload({ 
    Bucket: 'test-bucket', 
    Key: 'output.txt', 
    Body: rs, 
    }).promise() 

    console.log('response:') 
    console.log(response) 
} 

send().catch(err => { console.log(err) }) 

Nó nhận được kết quả này:

START UPLOAD 
OPEN 
DATA: <Buffer 73 6f 6d 65 74 68 69 6e 67> 
END 
CLOSE 
response: 
{ ETag: '"d41d8cd98f00b204e9800998ecf8427e"', 
    Location: 'https://test-bucket.s3.amazonaws.com/output.txt', 
    key: 'output.txt', 
    Key: 'output.txt', 
    Bucket: 'test-bucket' } 

Vấn đề là tập tin của tôi được tạo ra tại S3 (output.txt) có 0 Bytes.

Ai đó biết tôi đang làm gì sai?

Nếu tôi vượt qua bộ đệm trên Body thì nó hoạt động.

Body: Buffer.alloc(8 * 1024 * 1024, 'something'), 

Nhưng đó không phải là điều tôi muốn làm. Tôi muốn làm điều này bằng cách sử dụng một dòng để tạo ra một tập tin và đường ống một dòng để S3 miễn là tôi tạo ra nó.

Trả lời

2

Đây là một giao diện vấn đề API sử dụng NodeJS ReadableStreams. Chỉ cần bình luận mã liên quan đến sự kiện nghe 'data', giải quyết vấn đề.

const fs = require('fs') 
const S3 = require('aws-sdk/clients/s3') 

const s3 = new S3() 

const send = async() => { 
    const rs = fs.createReadStream('/home/osman/Downloads/input.txt') 
    rs.on('open',() => { 
    console.log('OPEN') 
    }) 
    rs.on('end',() => { 
    console.log('END') 
    }) 
    rs.on('close',() => { 
    console.log('CLOSE') 
    }) 
    // rs.on('data', (chunk) => { 
    // console.log('DATA: ', chunk) 
    // }) 

    console.log('START UPLOAD') 

    const response = await s3.upload({ 
    Bucket: 'test-bucket', 
    Key: 'output.txt', 
    Body: rs, 
    }).promise() 

    console.log('response:') 
    console.log(response) 
} 

send().catch(err => { console.log(err) }) 

Mặc dù nó là một API lạ, khi chúng ta lắng nghe 'data' sự kiện, ReadableStream bắt đầu chảy chế độ (nghe một sự kiện thay đổi trạng thái xuất bản/EventEmitter? Vâng, rất dễ bị lỗi ...). Vì một lý do nào đó, S3 cần bị tạm dừngReadableStream. Nếu whe đặt rs.on('data'...) sau await s3.upload(...) nó hoạt động. Nếu chúng tôi đặt rs.pause() sau rs.on('data'...) và befote await s3.upload(...), nó cũng hoạt động.

Bây giờ, điều gì sẽ xảy ra? Tôi chưa biết ...

Nhưng vấn đề đã được giải quyết, ngay cả khi nó không được giải thích đầy đủ.

+0

Điều tra tuyệt vời, tốt để biết điều đó. –

0
  1. Kiểm tra nếu tập tin /home/osman/Downloads/input.txt thực sự tồn tại và truy cập bằng Node.js quá trình
  2. Hãy xem xét sử dụng phương pháp putObject

Ví dụ:

const fs = require('fs'); 
const S3 = require('aws-sdk/clients/s3'); 

const s3 = new S3(); 

s3.putObject({ 
    Bucket: 'test-bucket', 
    Key: 'output.txt', 
    Body: fs.createReadStream('/home/osman/Downloads/input.txt'), 
}, (err, response) => { 
    if (err) { 
    throw err; 
    } 
    console.log('response:') 
    console.log(response) 
}); 

Không chắc chắn cách này sẽ làm việc với async .. await , tốt hơn để tải lên AWS: S3 hoạt động trước, sau đó thay đổi luồng.


UPDATE: Cố gắng thực hiện upload trực tiếp thông qua ManagedUpload

const fs = require('fs'); 
const S3 = require('aws-sdk/clients/s3'); 

const s3 = new S3(); 

const upload = new S3.ManagedUpload({ 
    service: s3, 
    params: { 
    Bucket: 'test-bucket', 
    Key: 'output.txt', 
    Body: fs.createReadStream('/home/osman/Downloads/input.txt') 
    } 
}); 

upload.send((err, response) => { 
    if (err) { 
    throw err; 
    } 
    console.log('response:') 
    console.log(response) 
}); 
+0

Tệp tồn tại và có thể truy cập được. Dòng 'DATA: 'nói rằng nó đã được đọc. 'putObject' gửi dữ liệu trên một lần yêu cầu HTTP, nó không truyền nó tới S3. 'async .. await' không phải là một vấn đề ở đây. Cảm ơn bạn! – osmanpontes

+0

@osmanpontes sẽ không tranh luận về điều này, bạn nói đúng. Bạn đã thử mã tôi đã đề nghị thay đổi phương thức 'putObject' thành' upload'? –

+0

@osmanpontes anyways, tôi đề nghị thử 'putObject' trong mục đích thử nghiệm –

Các vấn đề liên quan