npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

input-formdata

v1.0.2

Published

Receiving and parsing form data

Downloads

2

Readme

nodejs-input-formdata

Получение и парсинг данных форм.

Принимает данные из форм "application/x-www-form-urlencoded"/"multipart/form-data" и формирует объект с полученными данными.
Принимает в заданную директорию для временного хранения любое количество файлов из формы "multipart/form-data" методом "POST".
Учитывает ограничение на размер получаемых данных.
Автоматически удаляет просроченные файлы из директории для временного хранения.
Формирует функцию для перемещения загруженных файлов.
Позволяет использовать в названии полей формы точку . и/или квадратные скобки [] для помещения полученных данных в объект или в массив.
Опционально позволяет устанавливать способ сохранения файлов
- сохранение в файл каждой полученной порции данных файла (меньше потребляет ресурсов сервера)
- сохранение в файл только польностью полученных порций данных файла (более быстрый)

Метод "start" помещает функционал и полученные данные в req.input.
req.input.parse			- объект с полученными данными полей формы
req.input.parse[имя_поля] 	- значение из поля формы или значения группы полей формы при использовании в названии точки и/или квадратных скобок

Подключение

//Модуль получения данных
var input = require('input-formdata')(
	//Папка временных (загружаемых) файлов
	tmpDir 		: __dirname + '/_tmp/',
	//Ограничение данных, байт (0-без ограничения)			
	maxSize		: 1024*1024,
	//Срок хранения временных файлов, сек					
	storageTime	: 5*60, 					
	//Режим отладки
	isDebug		: false,
	//Режим
	saveFileChunk : true						
);

//Формируем задачу
var app = function(req, res) {

	...
		
	//Запуск модуля input -->req.input
	input.start (req, res, function () {
		console.log('Получены данные ' + req.method + ':', req.input.toString());

		...
		console.log(req.input.parse)
	});
};
//Создаем и запускаем сервер для задачи
var server = require('http').createServer(app);
server.listen(2020);

Примеры форм и результат в req.input.parse (полученные данные)

Пример 1. Форма "application/x-www-form-urlencoded" метод "GET"

<form enctype="application/x-www-form-urlencoded" method="get" action="/test">
	<input type="text" name="name1" value="1" />
	<input type="text" name="name2" value="example" />
	<input type="text" name="name3" value="2" />
	<textarea name="name4">text text text text text text text text text text</textarea>
</form>

Результат

{
	"name1": 1,
	"name2": "example",
	"name3": 2,
	"name4": "text text text text text text text text text text"
}

Пример 2. Форма "application/x-www-form-urlencoded" метод "POST"

<form enctype="application/x-www-form-urlencoded" method="post" action="/test">
	<input type="text" name="name1" value="1" />
	<input type="text" name="name2" value="example" />
	<input type="text" name="name3" value="2" />
	<textarea name="name4">text text text text text text text text text text</textarea>
</form>

Результат

{
	"name1": 1,
	"name2": "example",
	"name3": 2,
	"name4": "text text text text text text text text text text"
}

Пример 3. Форма "multipart/form-data" метод "GET"

<form enctype="multipart/form-data" method="get" action="/test">
	<input type="text" name="name1" value="1" />
	<input type="text" name="name2" value="example" />
	<input type="text" name="name3" value="2" />
	<textarea name="name4">text text text text text text text text text text</textarea>
</form>

Результат

{
	"name1": 1,
	"name2": "example",
	"name3": 2,
	"name4": "text text text text text text text text text text"
}

Пример 4. Форма "multipart/form-data" метод "POST". Отправка одного файла, например "my_file.jpg"

<form enctype="multipart/form-data" method="post" action="/test">
	<input type="text" name="field_1" value="1" />
	<input type="text" name="field_2" value="example" />
	<input type="text" name="field_3" value="2" />
	<textarea name="field_4">text text text text text text text text text text</textarea>
	<input type="file" name="userfile"/>
</form>

Результат

{
    "field_1": 1,
    "field_2": "example",
    "field_3": 2,
    "field_4": "text text text text text text text text text text",
    "userfile": {
        "tmp": "путь_и_случайное_название_файла_в_папке_временного_хранения.tmp",
        "mime": "image/jpeg",
        "ext": ".jpg",
        "size": 471349,
        "name": "my_file"
    }
}

Для перемещения в папку "uploads", например под тем же именем

if (req.input.parse.userfile) {
	req.input.parse.userfile.replaceTo('/uploads/' + req.input.parse.userfile['name'] + req.input.parse.userfile['ext']);
};

Пример 5. Использование скобок [] в названиях полей. Отправка нескольких файлов, например "my_file_1.jpg" и "my_file_2.jpg"

<form enctype="multipart/form-data" method="post" action="/test">
	<input type="text" name="field_1[]" value="1" />
	<input type="text" name="field_1[]" value="example" />
	<input type="text" name="field_2[2]" value="2" />
	<textarea name="field_2[4]">text text text text text text text text text text</textarea>
	<input type="file" name="userfiles[]" multiple/>
</form>

Результат

{
    "field_1": [
        1,
        "example"
    ],
    "field_2": [
        null,
        null,
        2,
        null,
        "text text text text text text text text text text"
    ],
    "userfiles": [
        {
            "tmp": "путь_и_случайное_название_файла_в_папке_временного_хранения.tmp",
            "mime": "image/jpeg",
            "ext": ".jpg",
            "size": 441496,
            "name": "my_file_1"
        },
        {
            "tmp": "путь_и_случайное_название_файла_в_папке_временного_хранения.tmp",
            "mime": "image/jpeg",
            "ext": ".jpg",
            "size": 471349,
            "name": "my_file_2"
        }
    ]
}

Для перемещения в папку "uploads", например под теми же именами

if (req.input.parse.userfiles) {
	for (var key in req.input.parse.userfiles) {
		if (req.input.parse.userfiles[key]) req.input.parse.userfiles[key].replaceTo('/uploads/' + req.input.parse.userfiles[key]['name'] + req.input.parse.userfiles[key]['ext']);
	}
};

Пример 6. Использование точек в названии полей.

<form enctype="multipart/form-data" method="post" action="/test">
	<input type="text" name="field_1.a" value="1" />
	<input type="text" name="field_1.b" value="example" />
	<input type="text" name="field_2.c" value="2" /></div>
	<textarea name="field_2.d.a">text text text text text text text text text text</textarea>
	<select name="field_2.d.b">
		<option value="0" selected="selected">0</option>
		<option value="1">1</option>
		<option value="2">2</option>
		<option value="3">3</option>
	</select>
	<input type="radio" name="field_2.radio" value="1" checked />
	<input type="radio" name="field_2.radio" value="2" />
</form>

Результат

{
    "field_1": {
        "a": 1,
        "b": "example"
    },
    "field_2": {
        "c": 2,
        "d": {
            "a": "text text text text text text text text text text",
            "b": 0
        },
        "radio": 1
    }
}

Пример 7. Использование точек и скобок [] в названии полей.

<form enctype="multipart/form-data" method="post" action="/test">
	<input type="text" name="field_1.a[]" value="1" />
	<input type="text" name="field_1.a[]" value="example" />
	<input type="text" name="field_2.a[2]" value="2" />
	<input type="checkbox" name="field_1.b[]" value="1" checked />
	<input type="checkbox" name="field_1.b[]" value="2" checked />
	<input type="checkbox" name="field_1.b[]" value="3" />
	<textarea name="field_2.c[4]">text text text text text text text text text text</textarea>
</form>

Результат

{
    "field_1": {
        "a": [
            1,
            "example"
        ],
        "b": [
            1,
            2
        ]
    },
    "field_2": {
        "a": [
            null,
            null,
            2
        ],
        "c": [
            null,
            null,
            null,
            null,
            "text text text text text text text text text text"
        ]
    }
}

Пример 8. Использование объекта XMLHttpRequest для отправки данных.

<script>
var lib_XHR = function () {
	var self = this;
	this.request = new XMLHttpRequest();
	this.onprogress = function(e) {
		console.log(Math.ceil(e.loaded/e.total*100) + '%');
	};
	this.success = function(result) {
		console.log(result);
	};
	this.onerror = function (e) {
		console.error('ERROR XHR:', '"Вызван request.onerror"', 'Ошибка:', e.toString());
	};
	//Отправка запроса
	this.run = function (url, form_data, success) {
		success 	= (success && typeof(success)=='function') ? (success) : (this.success);
		this.request.open('POST', url, true);
		 //Тип возвращаемых данных
		this.request.responseType = 'text';
		//Принудительно посылаем заголовок
		this.request.setRequestHeader('X-Requested-With', 'XmlHttpRequest');
		//Событие проверки состояния запроса запроса
		this.request.onreadystatechange = function() {
			if (self.request.readyState == 4 && self.request.status == 200) {
				try {
					success(JSON.parse(self.request.responseText));
				} catch (e) {
					success(self.request.responseText);
				}
			};
		};
		//Событие прогресса получения данных
		this.request.upload.onprogress = this.onprogress;
		//Событие ошибки запроса
		this.request.onerror = this.onerror;
		//Отправка запроса
		this.request.send(form_data);
	};
	//Отправка данных
	this.Send = function (url, data, success) {
		success 	= (success && typeof(success)=='function') ? (success) : (this.success);
		data 		= (data && typeof(data)=='object') ? (data) : ({});
		var formData = new FormData();
		for (var field in data) {
			formData.append(field, ((typeof(data[field])=='object' && !(data[field] instanceof File))) ? (JSON.stringify(data[field])) : (data[field]));
		};
		this.run (url, formData, success);
	};
	//Отправка формы
	this.Submit = function (form, success) {
		success = (success && typeof(success)=='function') ? success : this.success;
		if (!form) {
			return success('ERROE XHR.Submit: Форма не обнаружена');
		};
		var url = form.action;
		
		var formData = new FormData();
		for (var i=0; i<form.elements.length; i++) {
			if (!form.elements[i].name) continue;
			if (form.elements[i].files) {
				var keys = Object.keys(form.elements[i].files);
				if (keys.length==0) {
					//Если файлы не выбраны, возвращаем ''
					formData.append(form.elements[i].name,'');
				} else {
					//Если файлы выбраны возвращаем файл
					for (var j in keys) {
						formData.append(form.elements[i].name, form.elements[i].files[j]);
					};
				};
			} else {
				if (form.elements[i].type=='checkbox' && !form.elements[i].checked) {
					//formData.append(form.elements[i].name, '');
					continue;
				} else if (form.elements[i].type=='select-multiple') {
					for(var j=0;j<form.elements[i].options.length; j++) {
						if (!form.elements[i].options[j].selected) continue;
						formData.append(form.elements[i].name, form.elements[i].options[j].value);
					}
				} else {
					formData.append(form.elements[i].name, form.elements[i].value);
				}
			};
		};
		this.run (url, formData, success);
	};
};
var XHR = new lib_XHR();
</script>

<button id="btn_send" type="button">Отправить данные</button>
<div>Результат:</div>
<div id="result"></div>
<script>
//Событие прогресса запроса
XHR.onprogress = function(e) {
	document.querySelector('#result').innerHTML = Math.ceil(e.loaded/e.total*100) + '%';
};
//Событие нажатия кнопки
document.querySelector('#btn_send').onclick = function(e) {
	var data = {
		'field1.a' 	: 'value1',
		'field1.b' 	: 'value2',
		'field2' 	: 'value3',
		'field3' 	: 100,
	};
	/*
	//или такой вариант
	var data = {
		'field1' 	: {
			'a': 'value1',
			'b': 'value2'
		},
		'field2' 	: 'value3',
		'field3' 	: 100,
	};
	*/	
	XHR.Send('/test', data, function(result) {
		document.querySelector('#result').innerHTML = result;
	});
}
</script>

Результат

{
    "field1": {
        "a": "value1",
        "b": "value2"
    },
    "field2": "value3",
    "field3": 100
}

Пример 9. Использование объекта XMLHttpRequest для отправки формы с файлами, например "my_file_1.jpg" и "my_file_2.jpg".

<form enctype="multipart/form-data" method="post" action="/test">
	<input type="text" name="field_1[]" value="1" />
	<input type="text" name="field_1[]" value="example" />
	<input type="text" name="field_2[2]" value="2" />
	<textarea name="field_2[4]">text text text text text text text text text text</textarea>
	<input type="file" name="userfiles[]" multiple/>
	<button id="btn_send" type="button">Отправить форму</button>
</form>
<div>Результат:</div>
<div id="result"></div>
<script>
//Событие прогресса запроса
XHR.onprogress = function(e) {
	document.querySelector('#result').innerHTML = Math.ceil(e.loaded/e.total*100) + '%';
};
//Событие нажатия кнопки
document.querySelector('#btn_send').onclick = function(e) {
	XHR.Submit(this.form, function(result) {
		document.querySelector('#result').innerHTML = result;
	});
}
</script>

Результат

{
    "field_1": [
        1,
        "example"
    ],
    "field_2": [
        null,
        null,
        2,
        null,
        "text text text text text text text text text text"
    ],
    "userfiles": [
        {
            "tmp": "путь_и_случайное_название_файла_в_папке_временного_хранения.tmp",
            "mime": "image/jpeg",
            "ext": ".jpg",
            "size": 441496,
            "name": "my_file_1"
        },
        {
            "tmp": "путь_и_случайное_название_файла_в_папке_временного_хранения.tmp",
            "mime": "image/jpeg",
            "ext": ".jpg",
            "size": 471349,
            "name": "my_file_2"
        }
    ]
}

Для перемещения в папку "uploads", например под теми же именами

if (req.input.parse.userfiles) {
	for (var key in req.input.parse.userfiles) {
		if (req.input.parse.userfiles[key]) req.input.parse.userfiles[key].replaceTo('/uploads/' + req.input.parse.userfiles[key]['name'] + req.input.parse.userfiles[key]['ext']);
	}
};

Тестирование

Пример серверного кода для проверки работоспособности расположен в директории "_demo"
Для запуска установите конфигурацию модуля "output-view" (препроцессор шаблонов PHP)

Запуск тестового сервера из папки "_demo"

node server

Результат

http://localhost:2020