Сколько памяти съела программа на Python?

Некоторое время назад мне хотелось выяснить, сколько съедает памяти программа на Python и чем эта память занята. Тогда я не смог быстро найти решение и обошёлся без него, а вчера, совершенно случайно, наткнулся на целых два.

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

Следующий код (используется модуль Heapy):

from guppy import hpy
h = hpy()
print h.heap()

выведет вот такую, достаточно информативную, табличку:

Partition of a set of 132527 objects. Total size = 8301532 bytes.
Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)
0  35144  27  2140412  26   2140412  26 str
1  38397  29  1309020  16   3449432  42 tuple
2    530   0   739856   9   4189288  50 dict (no owner)

Другое решение — использовать Dowser, его интересная особенность — можно наблюдать за работающим кодом через веб-браузер.

# memdebug.py

import cherrypy
import dowser

def start(port):
    cherrypy.tree.mount(dowser.Root())
    cherrypy.config.update({
        'environment': 'embedded',
        'server.socket_port': port
    })
    cherrypy.server.quickstart()
    cherrypy.engine.start(blocking=False)

Подключаем в программу memdebug и вызываем memdebug.start.

Там же упоминается модуль PySizer, но его автор забросил работу и рекомендует использовать Heapy.

Оставить комментарий

IE и rgba

Век живи, век учись. Оказывается, в Internet Explorer есть возможность, через фильтры, указывать rgba-цвет:

.element{
    /*color = black, opacity = 0.6 */
    filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000,endColorstr=#99000000); /*AARRGGBB*/
    zoom: 1
}

Большая часть фильтров понимает цвет в формате argb (первая компонента — прозрачность).

4 комментария

Web Standards Days

27 и 28 ноября (может и на выходные останусь, как срастётся) еду в Минск на «Web Standards Days».

2 комментария

В Казань

Вылетаю сегодня (3 ноября) в Казань, в воскресенье (8 ноября) — назад.

Оставить комментарий

Сколько нужно людей, чтобы получился Chrome

Бобук рассказывает про количество людей, имеющих отношение к появлению Chrome:

Итого, представь себе что 10 миллионов долларов в акциях размазывается между разработчиками проекта. Такие небольшие проекты как Chrome в гугле затрагивают очень небольшую группу, скажем всего 500-600 человек разработчиков, 50-100 дизайнеров, 200-300 маркетологов, под сотню админов, сотня менеджеров. Итого на нос получается в пике 10 тысяч на лицо. Теперь подумай, что такое в Калифорнии 10 тысяч долларов _В АКЦИЯХ_, т. е. после реализации акций и уплаты налогов — у тебя на руках 5 тыщ долларов.

В ответ на вопрос откуда информация и по поводу численности:

Про команду разработки? Есть некотрые инсайдеры. Не, вообще команда разработки там примерно в 3 раза меньше, но есть же масса людей, которые учавствуют в проекте «парттайм», а доля будет такая же, как и у тех кто работал только над ним.

После недавней фразы Брина «мы ведем исследования небольшими группами по 200-300 человек», я уже ничему не удивляюсь.

Почти тысяча человек даже в самом минимальном случае!

13 комментариев

Компрессоры JavaScript и точка с запятой

Точка с запятой — один байт, перевод строки — один байт. Мне тут подумал, что лучше бы компрессоры JS выкидывали при сжатии не переводы строки, а точки с запятой (там где это возможно, конечно, например, пустой return в некоторых случаях нельзя завершить только переводом строки).

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

14 комментариев

Полезные rgba в IE

Вадим Макишвили описал несколько примеров применения rgba в Internet Explorer. Примеры очень и очень полезны, и я скопирую их (без картинок, за ними идите в исходный пост) к себе:

Сегодня, благодаря этому новому знанию, я понял как решить две труднорешаемые задачи. Издавна, чтобы сделать фон блока полупрозрачным, мы вынуждены были использовать или png-24 картинку в фоне или opacity-свойство.

Но в случае с png-24, для ИЕ6 нужно писать AlphaImageLoader фильтр, который катастрофически замедляет рендеринг страницы. А в случае с opacity приходилось придумывать трюки, чтобы дети блока не бледнели от родительского opacity.

А теперь проблему opacity можно забыть, как страшный сон: .block { background: #rgba } * html .block { filter:progid:DXImageTransform.Microsoft.gradient (startColorstr=#99000000, endColorstr=#99000000); }

В начальной и конечной позиции один и тот же RGB (000000) и добавляю перед ним одно и то же значение Alpha (99) Значение Alpha указывается в 16-тиричной системе, где 00 — полностью прозрачный, а ff — непрозрачный пиксел

Я протестировал скорость рендеринга страницы, на которой выливается 300 элементов с gradient-фильтром — он не замедляет рендеринг и это сильно радует.

Но этот случай описывает ситуацию, когда нужно сделать однотонный полупрозрачный цвет, как например в модальных диалогах, когда вся остальная страница затемняется.

Иногда использовать png-24 всё-таки необходимо, как например в случае, когда нужно обрезать длинную неразрывную строку, уводя ее градиентом в непрозрачность.

В этом случае можно использовать второй способ. .block { background: url(image.png) } * html .block { filter:progid:DXImageTransform.Microsoft.gradient (startColorstr=#00ffffff, endColorstr=#ffffffff, GradientType=1); }

GradientType принимает значение 1, если градиент рисуется слева-направо; и 0, если градиент сверху-вниз.

MSIE хороший браузер.

7 комментариев

Локальные переменные и JS

Читал тут по диагонали стандарт ECMAScript и подумалось мне, что сэмулировать локальные переменные (да, я осознаю, что это свойства объекта) можно вот так:

var a = 10;
with ( { a : 20 }) {
    alert(a);
}
alert(a);

Ожидаемый результат: сначала код выведет «20», потом — «10». Я ещё не задумывался над тем насколько это практично и изящно, просто придумалось.

Кстати, обратите внимание, что следующий код выведет «30», «30», «10», «30»:

var a = 10, b = 10;

with ({a:20}) {
    var a = 30, b = 30;
    alert(a);
    alert(b);
}

alert(a);
alert(b);

Добавлено 10 ноября 10:55: в комментариях почему-то подумали, что я не знаю о лексических замыканиях. Знаю, конечно.

6 комментариев

Ягоды

Ягоды (55.67КиБ)

Вчера жена домой заманивала, чтобы я пришёл пораньше с работы — купила клубники, выложила на тарелке и прислала мне фотографию.

9 комментариев

Попытка пересесть на Firefox. 2:0 в пользу «Оперы»

Посмотрел Firefox 3.6 beta 2, что сподвигло меня на очередную попытку пересесть на этот браузер с «Оперы»: скорость работы уже приблизилась к комфортной. Пересесть на Firefox хочется, прежде всего, из-за Firebug. Dragonfly в «Опере» — чудовищное глючное поделие, пользоваться которым некомфортно. Это совсем не похоже на ПО компании «Опера».

Неделю попользовался Firefox, не осилил. Нехватает тысячи мелочей, некоторые из которых не правятся плагинами. Например, почему при нажатии кнопки «Назад» в браузере, Firefox не показывает документ в том месте, где я остановил чтение? Мне что, на каждый чих закладку открывать?

Таких мелочей — очень много, слишком много, чтобы я мог спокойно пользоваться браузером. Приводить их полный список смысла нет, если даже многие их них правятся плагинами, я не готов тратить своё время, чтобы точить браузер под себя. И потом, чем больше плагинов, тем он больше тормозит.

Придётся, как и раньше, жить в двух программах. Это, кстати, моя вторая попытка переползти на Firefox.

64 комментария

Flash и безопасность

В качестве вялых воскресных препирательств, на «Хабре» как-то неожиданно вылезла мнимая проблема Flash — что загрузив ролик, можно попытаться получить доступ к cookie сайта или сделать какие-то другие интересные недобрые вещи.

Между тем, правил для защиты от таких «уязвимостей» всего два: выдавать при обращении к заливаемым пользователем Flash заголовки для скачивания (а то и вообще отдавать все пользовательские ролики с другого домена, порта или протокола) и указывать правильные параметры для проигрываемых роликов, залитых пользователем. Последнее — нехитрая наука, таких параметров всего три: allowScriptAccess, allowNetworking и allowFullScreen.

Их назначение легко расшифровывается по названию.

Параметр allowScriptAccess (введен во Flash 6.0.40.0) управляет доступом к JavaScript/DOM браузера и имеет три возможных значения: always, sameDomain и never. Пояснения, на мой взгляд, требует только значение sameDomain. Если выбрано это значение, то доступ предоставляется только скриптам, которые загружены с того же домена, что и страница, куда они подключены.

Следующий параметр, allowNetworking (работает, начиная с Flash 9.0) разрешает или запрещает обращение Flash к собственным сетевым функциям и сетевым функциям браузера. Имеет значения all, internal (запрещает использование сетевых функций браузера) и none.

Параметр allowFullScreen (Flash 9 и выше) принимает два возможных значения — false (выставлено по умолчанию) или true, которые (соотвественно) запрещают или разрешают использование полноэкранного режима.

Очевидно, что наиболее безопасные параметры — allowScriptAccess="never", allowNetworking="none" и allowFullScreen="false":

<object height="400" width="500">
<param name="allowScriptAccess" value="never" />
<param name="allowNetworking" value="none" />
<param name="movie" value="ролик.swf" />

<embed type="application/x-shockwave-flash"
     allowScriptAccess="never" allowNetworking="none" src="ролик.swf" height="400" width="500" />

</object>

Очень жаль, но значение «never» для параметра для параметра «allowScriptAccess» сейчас является deprecated, так же как и использование параметра allowNetworking, когда страница, на которой подключен ролик и сам ролик загружаются с одного и того же домена.

Насколько я понимаю, это связано с тем, что фирма Adobe, текущий владелец технологии Flash, не хочет брать на себя ответственно за утечку критичных данных через Flash-ролики. Вместо использования этих значений параметров рекомендуется загружать Flash-ролики с другого домена и не допускать того, чтобы критичные данные и ролики были доступны с одного домена.

12 комментариев

Уу-и-и-и-и

Самолётики (37.01КиБ)

Благодаря Паше Катурову и магазину «33 dodo» (кстати, жена, посмотри какие там наклейки в свою квартиру, сегодня будем смотреть и плакать вместе) теперь у меня на столе летают весёлые оранжевые самолётики.

11 комментариев

IE9

В блоге Microsoft, посвящённом их браузеру появилась статья об Internet Explorer 9. То, что есть сейчас уже очень неплохо — IE9 по скорости (если верить данным Microsoft) лишь чуть-чуть отстаёт от FF 3.6 и всего в два раза медленнее Chrome 4 (учитывая насколько он шустрый, это совсем неплохо).

Internet Explorer 9.0 проходит тест селекторов CSS3 с результатом 574 из 578 (IE8 — 330/578), тест ACID3 — 32% (IE8 — 20%), поддерживает border-radius (несмотря на более ранние заявления Microsoft, что CSS3 ещё пока слишком сырой, чтобы что-то из него реализовывать, кроме селекторов) и это только начало — ведь это даже ещё не альфа-версия!

Не могу поверить, что этот движок и есть «Газель» о которой говорили ранее, ведь «Газель» имела большие проблемы с производительностью, да и в статье из блога о безопасности и изоляции вкладок (основные фишки «Газели») ни слова.

P.S. Кстати, если покопаться, то можно найти как выглядит user-agent нового браузера: «Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/4.0)», IP, откуда заходили этим браузером, принадлежит городу Редмонд (в нём работает около 30 тысяч сотрудников Microsoft).

Движок, как видим, всё ещё называется «Trident», хотя номер смущает — 4.0, как мы знаем, версия, которая входит в IE8.

7 комментариев

Олимпийка

Ехал сегодня в метро, от нечего делать разглядывал пассажиров (забыл новую книгу загузить в телефон), случайно обратил внимание на дедушку, у него под полурасстёгнутом пальто, виднелась олимпийка. Помните такую? Как новая, а ведь ей лет 20.

Я много лет, с самого детства не слышал этого слова, не вспоминал, но стоило увидеть характерного василькового цвета «олимпийскую» кофту с молнией на горле, и оно мгновенно пришло на ум. Я сейчас поискал в «Яндексе», оказывается олимпийки до сих пор продаются (например «Адидас» их выпускает), но у меня язык не поворачивается их так называть. По воспоминаниям детства, олимпийка — только советская и только синяя. Я не помню кто её носил, кажется папа, а может я сам, а может все.

8 комментариев

«Жаворонкам» о «совах»

Жена показала прекрасный текст в журнале пользователя r2r на «@дневниках» о том «как чувствует себя „сова“ в мире, где работают с 8:30». Если ещё не читали, прочитайте. Если вы, к тому же, ещё и «жаворонок», читайте обязательно!

Я именно так себя и чувствую, когда приходится вставать рано. Я — «сова». Нет, это нельзя исправить. Девять лет школы, четыре года техникума, пять лет в университете и везде приходилось приходить рано. Как я не старался, но я спал на уроках и первых парах, ничего с этим поделать нельзя. По статистике 15% людей — яркие «жаворонки» и «совы», нас не переделать.

Добавлено 21 ноября 2009 15:32: Бирман у себя в комментариях очень правильно написал: «сова — это не тот, у кого режим дня ложиться в 2-3, вставать в 10-11, а тот, у кого только при таком режиме получается нормально жить».

8 комментариев

mod_rewrite: просмотр списка правил только один раз

У модуля mod_rewrite сервера «Апач» есть особенность, которая иногда портит много крови — после каждого переписывания URL, он просматривает список правил снова. Если ничего не предпринять, иногда происходит зацикливание, что ввергает новичков в ступор.

Мне эта особенность ни разу не пригодилась, но избавляться от неё приходится постоянно. В комментариях на «Хабре» к статье, название которой я вынес в заголовок, подсказали очень хороший способ, добавить первым правилом следующее:

# Don't loop.
RewriteCond %{ENV:REDIRECT_STATUS} !^$
RewriteRule .* - [L]

Если перезапись URL уже происходила, то любой URL оставляем без изменений и следующего цикла обработки уже не происходит.

10 комментариев

Функциональное тестирование и Selenium

Посмотрел «Selenium» — прекрасный, на мой взгляд, инструмент для автоматизации функционального тестирования. Из аналогов я нашёл только «Watir», но он мне показался сильно беднее (или только показался?). Платных аналогов много, в том числе от именитых IBM и HP, но хочется именно бесплатного.

Собственный опыт у меня пока небольшой (я написал несколько тестов и бегло прочитал документацию), а из прочитанного в сети я сделал вывод, что у «Селениум» есть проблемы. Вроде как он не любит фреймы (сомнительно) и стабильно работает только в Firefox (мне FF пока достаточно).

Я пока использовал только версию для Firefox (дополнение Selenium IDE). Самый простой способ изготовить тест выглядит следующим образом: открываем Selenium IDE, создаём новый тест, подготавливаем браузер (переходим на страницу, с которой тест начнётся), жмём на красную кнопку записи (справа на панели инструментов), в браузере выполняем какие-то действия, останавливаем запись и смотрим что получилось.

После того как последовательность действий в браузере была записана «Селениумом», нужно посмотреть что получилось, возможно что-то поправить. Язык простой и очень понятный, нужно лишь немного знать английский. В своём первом тесте я лишь вынес в переменную вводимую строку, чтобы позже использовать её в assertion и переделал селектор элемента с XPath на CSS (элементы можно выбирать через XPath, CSS, DOM, ID элемента, regexp и ещё несколькими способами), а так же добавил сам assert, ведь «Селениум» не знает что является успешным завершением теста.

Вот простенький тест, который я записал, что проиллюстрировать принцип:

сохраняем тестовую строку
store THIS-IS-TEST-STRING testPhrase

 открываем страницу в браузере
open /EvgenyStepanischev

 жмём на ссылку, в которой содержится указанное значение и ждём, когда браузер её полностью загрузит
clickAndWait link=EvgenyStepanischev / Тестирование

 жмём на ссылку, которая выбирается CSS-селектором
clickAndWait css=.edittab a.b-button-yellow

 печатаем
type postText ${testPhrase}

 жмём на клавишу с указанным ID
clickAndWait really_save_button1

 проверяем есть ли на странице наш текст
assertTextPresent ${testPhrase}

Чтобы тест выполнился, нужно указать для него базовый URL (по которому будет выполняться тест и нажать кнопку запуска теста и тест сьюта). На нашей внутренней «Вики» в «Яндексе» этот тест откроет мой кластер, найдёт там страницу «Тестирование», нажмёт на ней кнопку редактирования, напечатает в страницу «THIS-IS-TEST-STRING», сохранит изменение и убедится, что введённая строка появилась на странице.

Большинство потребностей покрывается языком «Селениума», для какие-то совсем уж сложных вещей можно использовать JavaScript (блок javascript { … }).

Есть возможность удалённого запуска тестов на нескольких браузерах и использование языков C#, Perl, Ruby, Python, PHP и Java, но я пока с этим богатством не разбирался, первые потребности вполне покрываются тем, что я уже знаю, дальнейшее — дело будущего.

Добавлено 22 ноября 2009 13:40: Андрей Ларионов подсказал ещё один бесплатный продукт — «Tellurium», но я не вижу преимуществ перед «Селениумом», зато вижу недостатки, например, усложнённый (по сравнению с «Селениумом») язык описания тестов.

8 комментариев

KeyRus

Олег, братишка, ты помнишь программу «KeyRus»? Отличный русификатор для DOS, им вся страна пользовалась, компактный, мощный, функциональный. Наше самонадеянное желание сделать меньший по размеру? Что мы тогда знали о сжатии и работе видеоадаптера? Помнишь как удивлялись, что после беты восьмой версии мы не могли найти релиз? 1994-й год, последняя версия, я ещё в техникуме учился, а интернет я увидел только через два или три года, браузер Lynx в текстовом терминале 286-го, подключенного через telnet под DOS к Unix-машине.

Случайно зашёл на страницу «кейруса» в Википедии, оказалось, что её автор Дмитрий Гуртяк умер в 1998-м, от саркомы мозга.

Видимо, в последние годы ему было не до «кейруса», мда.

5 комментариев

Импорт ЖЖ

Очень хочется импортировать сюда, в блог, свой старый ЖЖ. Конвертор давно готов (написал за пару дней ещё в феврале), но всё не решусь запустить — из-за «Яндекс.Ленты». Имеется неприятный баг, который проявляется, если использовать в RSS теги, позволяющие RSS-читалке «Яндекса» индексировать через RSS весь сайт целиком.

У меня они и используются. Если я симпортирую сюда весь ЖЖ, то пользователи «Яндекс.Ленты» увидят все эти записи (сколько их там не помню, ну пусть 800) как новые, что плохо, я такого себе позволить по отношению к читателям не могу, а что делать не знаю. Можно сделать импорт, но не показать эти записи роботу «Яндекса», тогда они не будут находиться через «Яндекс.Поиск по блогам», который я использую как поиск по своему сайту.

Куда не кинь, всюду клин.

А ещё и бы и старый сайт импортировать, с 11 ноября 2000 года по 4 июля 2003-го. Кстати, недавно было 9 лет как я веду этот сайт.

19 комментариев

未翻譯

Поднимался по мраморной лестнице во внутреннем дворике «Яндекса», капли дождя, накапливаясь на верхней площадке, срываются на ступеньку ниже, и ниже, и ниже. Я — исполин, идущий по долине муравьиных водопадов.

7 комментариев

Яндекс.рф

Компания «Яндекс» зарегистрировала домен Яндекс.рф:

domain:     XN--D1ACPJX3F.XN--P1AI
state:      REGISTERED, NOT DELEGATED, VERIFIED
org:        YANDEX, LLC.
phone:      +7 495 7397000
fax-no:     +7 495 7397070
e-mail:     noc@yandex.net
registrar:  RUCENTER-REG-RF
created:    2009.11.25
paid-till:  2010.11.25
source:     TCI

Есть так же Рамблер.рф, Кремль.рф, Москва.рф, Россия.рф, Мир.рф, Труд.рф, Газета.рф и, видимо, многие другие.

Вполне себе развлечение — угадать какие имена могут быть заняты.

13 комментариев

Web Standards Days через 2 дня

Завтра-послезавтра мы с женой Минске, в первый день погуляем по городу и отметим день рождения жены, во второй день я на «Web Standards Days» (впрочем, все участвующие уже в курсе, из письма организаторов).

Оставить комментарий

Минск

Немного не повезло на въезде в город — прилетал Медведев и прямую трассу в Минск закрыли для простых смертных, зато таксист (ехали из аэропорта) сполна отработал двойной тариф, который он с нас слупил. Заехали в гостиницу «Беларусь» — чистенькую, но совковую. Совковость чувствуется во всём, в номере холодно (+6 на улице, в номере, похоже, не топят), персонал хамит, порою действует соверешенно неадекватно.

Складывается ощущение (не знаю так ли это), что ресторан «Панорама» на 22-м этаже гостиницы — самая высокая точка города, когда смотришь из окна, не видно, чтобы где-то были здания выше. Погуляли по городу, холодно, исчезающе мало кафе, но чисто и благопристойно. Много заботятся о безопасности на дорогах — большие знаки, яркие (светодиодные, плоские) светофоры, широкие дорогие, велосипедные дорожки. Общее ощущение — город скучноватый, но откуда это родилось я не решусь сказать.

Беларуский рубль — это примерно в 95 раз меньше, чем российский, что незаурядно травмирует мозг поначалу (400 тысяч за номер в отеле?! 127 тысяч за такси??!), но постепенно начинаешь незаметно убирать два нуля и испокаиваешься (сколько надо доплатить за завтрак — 32000? а! это же где-то 320 рублей).

9 комментариев

Input multiple

Я как-то пропустил, хотя сам участвовал в голосовании за эту фичу, что бете FF 3.6 появилась возможность выбрать несколько файлов при загрузке (это часть стандарта WebForms 2). Простой пример использования:

<input type="file" name="input" multiple="true" />

Ещё более интересно, что в свежей бете (№4) этого браузера есть возможность (как я понял) получить доступ к выбранным файлам из веб-приложения.

Попробовал посмотреть как выгдядит прикрепление нескольких файлов со стороны PHP, оказалось всё просто — достаточно сказать PHP, что из входящих данных нужно сделать массив и всё работает (например, указать name=«input[]»): в каждом поле каждого элемента массива $_FILES содержится массив значений. Вот как это выглядит для двух файлов:

array(1) {
  ["input"]=>
  array(5) {
    ["name"]=>
    array(2) {
      [0]=>
      string(14) "2009.09.23.jpg"
      [1]=>
      string(14) "2009.08.25.jpg"
    }
    ["type"]=>
    array(2) {
      [0]=>
      string(10) "image/jpeg"
      [1]=>
      string(10) "image/jpeg"
    }
    ["tmp_name"]=>
    array(2) {
      [0]=>
      string(18) "Z:\tmp\php3740.tmp"
      [1]=>
      string(18) "Z:\tmp\php3741.tmp"
    }
    ["error"]=>
    array(2) {
      [0]=>
      int(0)
      [1]=>
      int(0)
    }
    ["size"]=>
    array(2) {
      [0]=>
      int(35005)
      [1]=>
      int(63030)
    }
  }
}

Конструкция работает в Chrome с версии 3.0.191.0 и в Safari с версии 4.0.1. К сожалению, в Opera 10.20 alpha 1 поддержки нет, в IE8 — тоже.

Добавлено 29 ноября 2009 23:08: оказывается, «Опера» поддерживала с версии 3.5 загрузку сразу нескольких файлов в обычном, «однофайловом» диалоге, но в 7-й версии эту возможность открутили. Так что «Опера» первый браузер, где это реализовали.

Добавлено 29 ноября 2009 23:14: «Опера» 9.0 и выше поддерживает загрузку множества файлов в одном контроле, достаточно указать параметры min и max:

<form enctype="multipart/form-data" method="post">
   <input type="file" min="1" max="9999" name="file" />
   <input type="submit" name="submit" />
</form>

Плохие новости заключаются в том, что PHP такой запрос от «Оперы» разбирать не умеет.

Добавлено через год: в «Опере» 11 атрибуты «min» и «max» удалили, но зато работает «multiple».

2 комментария

Input multiple-2

По мотивам предыдущего поста. Чтобы Opera 9+ (а так же 3.5—6.05), Firefox 3.6+, Chrome 3.0.191.0+ и Safari 4.0.1+ позволили выбрать несколько файлов в диалоге загрузки файлов, нужно написать вот такой код:

<form enctype="multipart/form-data" method="post">
   <input type="file" min="1" max="9999" name="file[]" multiple="true" />
   <input type="submit" name="submit" />
</form>

Я указал «file[]» для того, чтобы PHP сразу разложил полученные файлы по массиву $_FILES. К сожалению, запрос от «Оперы» PHP понимает неверно, так как «Опера» шлёт такой запрос в формате multipart/mixed. К счастью, PHP в этом случае положит содержимое файлов одним MIME-куском прямо в $_POST[’file’][0], а там его уже можно разобрать (надеюсь, директива magic_quotes_gpc у вас отключена).

Я попробовал, это несложно. Для того, чтобы разобрать MIME-секцию, я использовал PECL-модуль mailparse (есть версия для Windows):

if (isset($_POST['file'], $_POST['file'][0])) {

    if ($idx = strpos($_POST['file'][0], "\n")) {
        $bound = substr($_POST['file'][0], 2, $idx-2);

        $body  = "MIME-Version: 1.0\nContent-type: multipart/form-data; boundary={$bound}\n\n".
                 $_POST['file'][0];

        unset($_POST['file'][0]);
        $f = &$_FILES['file'];

        $f['name'] = $f['type'] = $f['tmp_name'] = $f['error'] = $f['size'];

        $msg = mailparse_msg_create();

        if (mailparse_msg_parse($msg, $body)) {
            $i = 0;

            foreach(mailparse_msg_get_structure($msg) as $st) {

                $section = mailparse_msg_get_part($msg, $st);

                $data = mailparse_msg_get_part_data($section);

                if ($data['content-type'] == 'multipart/form-data') {
                    continue; 
                }
            
                ob_start();
                if (mailparse_msg_extract_part($section, $body)) {
                    $tmp = tempnam(sys_get_temp_dir(), 'php');
                    file_put_contents($tmp, ob_get_clean());

                    $f['name'][$i] = $data['disposition-filename'];
                    $f['type'][$i] = $data['content-type'];
                    $f['tmp_name'][$i] = $tmp;
                    $f['error'][$i] = 0;
                    $f['size'][$i] = filesize($tmp);

                    $i++;
                } else {
                    ob_end_clean();
                }
            }
        }
        unset($f);

        mailparse_msg_free($msg);
    }
}

var_dump($_FILES); // результат помещатся в $_FILES, не забудьте удалить временные файлы после обработки!

У меня ожидается, что содержимое файлов будет передано как параметр «file[]» (в $_POST это будет $_POST[’file’][0]), но пример несложно переделать на любое другое имя или сделать это имя параметром.

5 комментариев

← сюда туда →