2017-05-23 1 views
5

Je suis en train d'utiliser la méthode télécharger de s3 utilisant un ReadableStream du module fs.méthode de téléchargement Javascript AWS SDK S3 avec flux de corps générant fichier vide

Le documentation dit qu'un ReadableStream peut être utilisé à Body param:

corps - (Tampon, Array tapées, Blob, String, ReadableStream) les données de l'objet.

également la description du procédé de mise en ligne est:

Uploads un tampon de taille arbitraire, goutte, ou le flux, en utilisant la manipulation simultanée de parties intelligente si la charge utile est suffisamment grande.

En outre, ici: Upload pdf generated to AWS S3 using nodejs aws sdk le @shivendra dit qu'il peut utiliser un ReadableStream et cela fonctionne.

Ceci est mon code:

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

Il devient cette sortie:

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

Le problème est que mon fichier généré à S3 (sortie.txt) a 0 Octets. Quelqu'un sait ce que je fais mal?

Si je passe un tampon sur Body cela fonctionne.

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

Mais ce n'est pas ce que je veux faire. Je voudrais le faire en utilisant un flux pour générer un fichier et diriger un flux vers S3 tant que je le génère.

Répondre

2

Il est un problème d'interface API à l'aide NodeJS ReadableStreams. Il suffit de commenter le code lié à l'événement d'écoute 'data', résout le problème.

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

Bien qu'il soit une API étrange, lorsque nous écoutons événement 'data', le ReadableStream commence le qui coule en mode (écouter un événement de changement d'état éditeur/EventEmitter? Oui, très sujette aux erreurs ...). Pour une raison quelconque, le S3 a besoin d'un mis en pauseReadableStream. Si whe mettre rs.on('data'...) après await s3.upload(...) cela fonctionne. Si nous mettons rs.pause() après rs.on('data'...) et befote await s3.upload(...), cela fonctionne aussi.

Maintenant, que se passe-t-il? Je ne sais pas encore ...

Mais le problème a été résolu, même s'il n'est pas complètement expliqué.

+0

Grande enquête, bon à savoir. –

0
  1. Vérifiez si le fichier /home/osman/Downloads/input.txt existe réellement et accessible par le processus de Node.js
  2. Tenir compte utiliser putObject méthode

Exemple:

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

Je ne sais pas comment cela va fonctionner avec async .. await , mieux de faire le téléchargement sur AWS: S3 fonctionne d'abord, puis change le flux.


MISE À JOUR: Essayez de mettre en œuvre le téléchargement directement via 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

Le fichier existe et est accessible. La ligne 'DATA: ' dit qu'elle a été lue. 'putObject' envoie les données sur une requête HTTP, il ne les transmet pas à S3. 'async .. await' n'est pas un problème ici. Je vous remercie! – osmanpontes

+0

@osmanpontes ne discuterait pas sur ce point, vous avez raison. Avez-vous essayé le code que j'ai suggéré de changer la méthode 'putObject' en' upload'? –

+0

@osmanpontes de toute façon, je suggère d'essayer 'putObject' dans le but de test –