2017-05-23 65 views
5

Próbuję użyć metody przesłać z s3 użyciu ReadableStream z modułu fs.JavaScript AWS SDK S3 metoda przesyłania strumienia z ciała generowania pusty plik

documentation mówi, że ReadableStream może być stosowany w Body param:

Body - (bufor, wpisywanych tablicy, Blob, String, ReadableStream) dane obiektu.

Również przesyłania opis sposób jest następujący:

Wysyła dowolnie wielkości bufora, blob, lub strumienia, programowalnych równoczesne manipulowanie częściami, gdy ładunek jest wystarczająco duży.

Również tutaj: Upload pdf generated to AWS S3 using nodejs aws sdk @shivendra mówi, że może używać ReadableStream i działa.

To jest mój kod:

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) }) 

Robi się to wyjście:

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' } 

Problemem jest to, że mój plik generowany na S3 (Output.txt) ma 0 bajtów.

Ktoś wie, co robię źle?

Jeśli przekażę bufor na Body, to działa.

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

Ale to nie jest to, co chcę robić. Chciałbym to zrobić za pomocą strumienia, aby wygenerować plik i potokować strumień do S3, tak długo jak go generuję.

Odpowiedz

2

jest to kwestia interfejsu API za pomocą NodeJS ReadableStreams. Po prostu skomentuj kod związany z wydarzeniem nasłuchiwania 'data', rozwiązuje problem.

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) }) 

Choć jest to dziwne API, gdy słuchamy 'data' razie ReadableStream uruchomieniu płynący tryb (słuchanie ze zdarzeniem zmieniającym stan wydawca/EventEmitter? Tak, bardzo podatny na błędy ...). Z jakiegoś powodu S3 potrzebuje pauząReadableStream. Jeśli whe umieścić rs.on('data'...) po await s3.upload(...) to działa. Jeśli umieścimy rs.pause() po rs.on('data'...) i befote await s3.upload(...), to też działa.

Co się stało? Nie wiem jeszcze ...

Ale problem został rozwiązany, nawet jeśli nie został całkowicie wyjaśniony.

+0

Wielkie śledztwo, dobrze to wiedzieć. –

0
  1. Sprawdź, czy plik /home/osman/Downloads/input.txt faktycznie istnieje i dostępne node.js procesu
  2. rozważyć podawanie leku putObject metoda

Przykład:

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) 
}); 

Nie wiem, jak to będzie działać z async .. await , lepiej zrobić przesyłanie do AWS: najpierw S3, a potem zmienić przepływ.


UPDATE: Spróbuj Wdrożenie przesyłać bezpośrednio poprzez 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

Plik istnieje i jest dostępny. Wiersz 'DATA: ' mówi, że został odczytany. 'putObject' wysyła dane na żądanie HTTP, nie przesyła go do S3. 'async .. await' nie stanowi tu problemu. Dziękuję Ci! – osmanpontes

+0

@osmanpontes nie kłóciłoby się o to, masz rację. Czy próbowałeś kodu Sugerowałem zmianę 'putObject' na metodę' upload'? –

+0

@osmanpontes anyways, sugeruję wypróbować 'putObject' w celu testowania –