2016-07-26 9 views
9

Cieszę się, że see AWS obsługuje teraz dane wieloczęściowe/formularzy na AWS Lambda, ale teraz, gdy surowe dane są w mojej funkcji lambda, w jaki sposób mogę je przetworzyć ?Parse multipart/form-data z treści jako ciąg na AWS Lambda

Widzę, że multiparty jest dobrą biblioteką wieloczęściową w węźle do przetwarzania wieloczęściowego, ale jej konstruktor oczekuje żądania, a nie nieprzetworzonego łańcucha.

Komunikat wejściowy Otrzymuję na mojej funkcji Lambda (po zastosowano szablon mapowania ciała) to:

{ "rawBody": "--ce0741b2-93d4-4865-a7d6-20ca51fe2689\r\nContent-Disposition: form-data; name=\"Content-Type\"\r\n\r\nmultipart/mixed; boundary=\"------------020601070403020003080006\"\r\n--ce0741b2-93d4-4865-a7d6-20ca51fe2689\r\nContent-Disposition: form-data; name=\"Date\"\r\n\r\nFri, 26 Apr 2013 11:50:29 -0700\r\n--ce0741b2-93d4-4865-a7d6-20ca51fe2689\r\nContent-Disposition: form-data; name=\"From\"\r\n\r\nBob <[email protected]>\r\n--ce0741b2-93d4-4865-a7d6-20ca51fe2689\r\nContent-Disposition: form-data; name=\"In-Reply-To\"\r... 

itp i jakiś plik danych.

Szablon mapowanie ciała używam jest

{ 
    "rawBody" : "$util.escapeJavaScript($input.body).replaceAll("\\'", "'")" 
} 

Jak mogę analizować te dane do acecss pól i plików umieszczonych na mojej funkcji Lambda?

Odpowiedz

8

ten pracował dla mnie - za pomocą busboy

kredyty należne Parse multipart/form-data from Buffer in Node.js którego skopiowane większość z tego.

const busboy = require('busboy'); 

const headers = { 
    'Content-Type': 'application/json', 
    'Access-Control-Allow-Origin': '*', 
    'Access-Control-Allow-Methods': 'OPTIONS, POST', 
    'Access-Control-Allow-Headers': 'Content-Type' 
}; 

function handler(event, context) { 
    var contentType = event.headers['Content-Type'] || event.headers['content-type']; 
    var bb = new busboy({ headers: { 'content-type': contentType }}); 

    bb.on('file', function (fieldname, file, filename, encoding, mimetype) { 
    console.log('File [%s]: filename=%j; encoding=%j; mimetype=%j', fieldname, filename, encoding, mimetype); 

    file 
    .on('data', data => console.log('File [%s] got %d bytes', fieldname, data.length)) 
    .on('end',() => console.log('File [%s] Finished', fieldname)); 
    }) 
    .on('field', (fieldname, val) =>console.log('Field [%s]: value: %j', fieldname, val)) 
    .on('finish',() => { 
    console.log('Done parsing form!'); 
    context.succeed({ statusCode: 200, body: 'all done', headers }); 
    }) 
    .on('error', err => { 
    console.log('failed', err); 
    context.fail({ statusCode: 500, body: err, headers }); 
    }); 

    bb.end(event.body); 
} 

module.exports = { handler }; 
0

Opierając się na @AvnerSo: s odpowiedzi, tutaj jest prostsza wersja funkcji, która otrzymuje ciało żądania i nagłówków jako parametry i zwraca obietnicę obiektu zawierającego pola formularza i wartości (pliki pomijam):

const parseForm = (body, headers) => new Promise((resolve, reject) => { 
    const contentType = headers['Content-Type'] || headers['content-type']; 
    const bb = new busboy({ headers: { 'content-type': contentType }}); 

    var data = {}; 

    bb.on('field', (fieldname, val) => { 
    data[fieldname] = val; 
    }).on('finish',() => { 
    resolve(data); 
    }).on('error', err => { 
    reject(err); 
    }); 

    bb.end(body); 
}); 
0

Jeśli chcesz uzyskać gotowy do użycia obiekt, oto funkcja, której używam. Zwraca obietnicę i obsługuje błędy:

import Busboy from 'busboy'; 
import YError from 'yerror'; 
import getRawBody from 'raw-body'; 

const getBody = (content, headers) => 
    new Promise((resolve, reject) => { 
     const filePromises = []; 
     const data = {}; 
     const parser = new Busboy({ 
     headers, 
     }, 
     }); 

     parser.on('field', (name, value) => { 
     data[name] = value; 
     }); 
     parser.on('file', (name, file, filename, encoding, mimetype) => { 
     data[name] = { 
      filename, 
      encoding, 
      mimetype, 
     }; 
     filePromises.push(
      getRawBody(file).then(rawFile => (data[name][content] = rawFile)) 
     ); 
     }); 
     parser.on('error', err => reject(YError.wrap(err))); 
     parser.on('finish',() => 
     resolve(Promise.all(filePromises).then(() => data)) 
    ); 
     parser.write(content); 
     parser.end(); 
    })