Разобрать значение формы с грозным именем файла

Я использую грозный для обработки загрузки файлов в NodeJs. Я немного застрял в разборе значений полей.

Как мне передать значение project_id обработчику формы, чтобы я мог записать параметр в свое имя файла?

<input type="text" id="project_id" value="{{projects._id}}" readonly>

ИЗМЕНИТЬ

Чтобы быть более конкретным, вот подробное представление моей обработки загрузки формы:

app.post('/uploads/', function (req, res){
    var form = new formidable.IncomingForm();
    form.parse(req, function (err, fields, files) {
        res.writeHead(200, {'content-type': 'image/jpeg'});
        res.write('received upload: \n\n');
        var project = fields.project_id;
        res.end(util.inspect(project, {fields: fields, files: files}));
    });

    form.on('end', function(project, fields, files){ 
        console.log(project); 
        /*Temporary location of our uploaded file */
        var temp_path = this.openedFiles[0].path;
        /*The file name of the uploaded file */
        var file_name =  project + '.' + this.openedFiles[0].name;

Я могу зарегистрировать var project в части form.parse. Но я не получаю переменную в части form.on('end'....

HTML-форма

<form   id="uploadForm"
    enctype="multipart/form-data"
    action="/uploads/"
    method="post">
    <input type="text" name="project_id" id="project_id" value="{{projects._id}}" readonly>
    <input multiple="multiple" type="file" name="upload" />
    <button type="submit">Upload</button>
</form>

person Wandkleister    schedule 08.05.2015    source источник
comment
Есть ли причина, по которой вы используете formidable напрямую вместо body-parser? Предполагая, что вы отправляете эту форму в экспресс-приложение, синтаксический анализатор будет проще. Например. app.use(bodyParser.urlencoded()) даст вам project_id в req.body.   -  person Andrew Lavers    schedule 08.05.2015
comment
Я обрабатываю загрузку файлов, поэтому для выражения дается не только идентификатор проекта. Забыл это в своем первом посте, извините.   -  person Wandkleister    schedule 08.05.2015


Ответы (2)


Обратный вызов end в Formidable не принимает никаких параметров, но я не уверен, что вам вообще нужно вызывать его, если вы используете обратный вызов parse. Я думаю, что вы ищете что-то вроде этого:

var fs = require('fs');
app.post('/uploads', function(req, res, next) {
    var form = new formidable.IncomingForm();
    form.parse(req, function(err, fields, files) {
        if (err) next(err);

        // TODO: make sure my_file and project_id exist    
        fs.rename(files.my_file.path, fields.project_id, function(err) {
            if (err) next(err);
            res.end();
        });
    });
});

Вам нужно будет прослушивать событие end(), если вы решили не использовать обратный вызов parse, например:

new formidable.IncomingForm().parse(req)
    .on('file', function(name, file) {
        console.log('Got file:', name);
    })
    .on('field', function(name, field) {
        console.log('Got a field:', name);
    })
    .on('error', function(err) {
        next(err);
    })
    .on('end', function() {
        res.end();
    });
person Andrew Lavers    schedule 08.05.2015
comment
Кажется, это ничего не загружает... Нет ли возможности использовать fields.project_id. Для меня не имеет смысла, что я не могу использовать его при записи файла. - person Wandkleister; 08.05.2015
comment
Вы должны иметь возможность загружать как файл, так и поле в одном запросе. Я проверил свой код с помощью postman. Можете ли вы опубликовать всю свою html-форму? - person Andrew Lavers; 08.05.2015
comment
Отредактировал в своем первом сообщении - person Wandkleister; 08.05.2015
comment
Я протестировал ваш HTML-код с помощью своего кода (после изменения ввода project_id на жестко закодированное значение), и он отлично работает. Можете ли вы опубликовать образец того, как выглядит ваш рендеринг HTML, а не шаблон? - person Andrew Lavers; 08.05.2015
comment
Ааа, черт возьми, я сделал ошибку, скопировав ваше решение. Работает! Большое спасибо!!! Последний вопрос: как изменить путь сохранения изображения? Лучшим способом было бы установить project_id в качестве подкаталога в каталоге изображений. - person Wandkleister; 08.05.2015
comment
Ваше здоровье! Обязательно отметьте как ответ :-) Второй параметр fs.rename - это путь сохранения. - person Andrew Lavers; 08.05.2015
comment
Салют дружище! Но это не создает подкаталог fs.rename(files.upload.path, 'uploads/'+fields.project_id,... Поскольку я пробовал это, у файлов нет расширения файла, только project_Id. Сводит меня с ума - person Wandkleister; 08.05.2015
comment
Если каталог не существует, вы можете создать его с помощью fs.mkdir - person Andrew Lavers; 08.05.2015
comment
Первая обратная косая черта вызвала проблему. 'uploads/' + fields.project_id работает. А проблема с отсутствующим расширением файла исправлена ​​так: fs.rename(files.upload.path, 'uploads/' + fields.project_id + files.upload.name. Спасибо Андрей, хорошего дня! - person Wandkleister; 08.05.2015
comment
Это хорошо, кто-нибудь также добавил к этому модульные тесты. Мне интересно, как вы издеваетесь над файлом с запросом - person BlackBurn027; 08.05.2020

Скрипт на стороне клиента:

    //Upload the file
    var fd = new FormData();
    //Take the first selected file
    fd.append("dbDocPath", 'invoices/' + file.name);
    fd.append("file", file);
    $http({
            method: 'POST',
            url: $rootScope.apiUrl + 'uploadDocToServer',
            data: fd,
            headers: {
                'Content-Type': undefined
            },
            //prevents serializing payload.  don't do it.
            transformRequest: angular.identity,
        }).success(function (response) {
           if (response.success) {
           }
   })

Скрипт на стороне сервера:

var fileDir = path.join(__dirname, '/../uploads');

// create an incoming form object
var form = new formidable.IncomingForm();
var dbDocPath = '';
form.parse(req)
        .on('field', function (name, field) {
            //console.log('Got a field:', field);
            //console.log('Got a field name:', name);
            dbDocPath = field;
        })
        .on('file', function (name, file) {
            //console.log('Got file:', name);

            // specify that we want to allow the user to upload multiple files in a single request
            //form.multiples = true;

            // store all uploads in the /uploads directory
            form.uploadDir = fileDir;

            fs.rename(file.path, path.join(form.uploadDir, file.name));

            // every time a file has been uploaded successfully,
            // rename it to it's orignal name

            var bucket = new AWS.S3();
            //console.log(dbDocPath);

            var params = {
                Bucket: DocsConfig.bucketName,
                Key: dbDocPath,
                Body: fs.createReadStream(path.join(form.uploadDir, file.name)),
                ACL: 'public-read'
            };

            bucket.putObject(params, function (perr, pres) {
                if (perr) {
                    //console.log("Error uploading data: ", perr);
                } else {
                    fs.unlinkSync(path.join(form.uploadDir, file.name));
                    //console.log("Successfully uploaded data", pres);
                }
            });
        })
        .on('error', function (err) {
            res.send({'success': false, error: err});
        })
        .on('end', function () {
            res.send({'success': true});
        });
// parse the incoming request containing the form data
//form.parse(req);

Просто имейте в виду, что последовательность отправки параметров в formData() должна быть такой же, как указано в приведенном выше коде, поскольку для загрузки файла требуется путь для загрузки в судьбу.

person Rahul Mankar    schedule 23.05.2017
comment
Прохладный, используя функциональную переменную, чтобы установить поле перед обработкой файла. Ваш объект AWS может использовать некоторые поля ключа, секрета и региона. - person Joshua Majebi; 10.03.2018