NodeJS Multipart/form-data с массивами

86
5

У меня возникли проблемы с использованием данных multipart/form-data enctype и отправки входов с тем же именем, которые будут получены в виде массива. Я могу только получить загруженное изображение ИЛИ входы массива, но не оба одновременно.

Например, у меня есть эта форма:

<form method="post" action="/test">
<input name="testinput" value="valueA">
<input name="testinput" value="valueB">
<input type="file" name="fileattachment">
<input type="submit" value="Submit">
</form>

Если я задаю форму enctype как multipart/form-data, например:

<form method="post" action="/test" enctype="multipart/form-data">

В конечном итоге я получаю "файловую привязку" в моем приложении NodeJS, но я получаю последнее значение для "testinput", например:

//req.body
//---
{
testinput: 'valueB' // I'm missing valueA!
}

//req.files
//---
{
fileattachment: {
name: 'biglogo.png',
data: <Buffer 89 ... >,
encoding: '7bit',
mimetype: 'image/png',
mv: [Function]
}
}

Если enctype не установлен, данные "testinput" поступают как массив, но "fileattachment" теряется, и я получаю только имя загруженного файла, например:

//req.body
//---
{
testinput: ['valueA', 'valueB'],
fileattachment: 'some_picture.png' // Useless for file uploading
}

Я думаю, что это имеет какое-то отношение к тому, как я настроил экспресс-парсер, но я не могу понять правильную конфигурацию. Это моя настройка (упрощенная для соответствующего кода):

var express = require('express');
var fileUpload = require('express-fileupload');
var bodyParser = require('body-parser');

var app = express();
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
app.use(fileUpload()); // Must be placed after, not before, bodyparser use, otherwise files fail to be uploaded correctly...

app.post('/test', function(req, res) {
// Some code
});

Кроме того, это мой файл package.json:

{
"name": "my-app",
...
"dependencies": {
"body-parser": "~1.15",
"express": "~4.14",
"express-fileupload": "^0.0.5"
}
}

Это выполняется на node/6.9.1

Я видел этот очень похожий вопрос Multipart/form-data с массивами, но ему 2 года, не fileUpload и, похоже, не использует зависимость fileUpload.

Кроме того, я пробовал подход, предложенный ответом на этот вопрос. Обработка входных массивов в экспресс-формах? , но все, что я получаю на сервере, выглядит как текст вместо массивов, например:

{ 
'something[0][testinput]': 'valueA',
'something[1][testinput]': 'valueB'
}

Что мне не хватает? Что я должен попробовать?

спросил(а) 2021-01-19T17:27:05+03:00 2 месяца, 3 недели назад
1
Решение
97

Я смог получить желаемый результат, переключившись с express-fileupload на Multiparty

Настройка:

var express = require('express');
var bodyParser = require('body-parser');

app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());

Мой код:

var multiparty = require('multiparty');
app.post('/test', function(req, res) {
(new multiparty.Form()).parse(req, function(err, fields, files) {
// handling fields and files code
});
});

Поля:

{ 
testinput: ['valueA', 'valueB']
}

файлы:

{ 
fileattachment: [
{
fieldName: 'fileattachment',
originalFilename: 'biglogo.png',
path: '/tmp/blablaasdfgh.png',
headers: [Object],
size: 10130
}
]
}

Как вы можете видеть, входы объединены вместе в массив, и файл кажется правильно полученным.

ответил(а) 2021-01-19T17:27:05+03:00 2 месяца, 3 недели назад
44

У меня была такая же проблема с использованием express-fileupload, я смог заставить ее работать с этой функцией

ProjectController.prototype.teste = async function (request, response, next) {
let documents = parseFormDate(request.body, request.files);
return response.status(200).json({ 'body': request.body, 'documents': documents });
};

а также

const parseFormDate = (field, files) => {
let documents = []
for (const key in files) {
if (files.hasOwnProperty(key)) {
const file = files[key];
if (field[key]) {
documents.push({ title: field[key], document: file })
delete field[key];
}

delete files[key];
}
}

return documents;
}

ответил(а) 2021-01-19T17:27:05+03:00 2 месяца, 3 недели назад
45

Сконфигурируйте библиотеку express-fileupload для использования свойства parseNested следующим образом:

const fileUpload = require('express-fileupload');
app.use(fileUpload({
parseNested: true // magic
}));

ответил(а) 2021-01-19T17:27:05+03:00 2 месяца, 3 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема