Организация хранения личных файлов локально и в облаках
Статья написана для тех, кто ищет наилучший способ организации хранения и управления своими файлами и хочет при этом пользоваться всеми преимуществами наиболее распространенных на сегодняшний день облачных хранилищ.
Найти
- Со временем мы накапливаем все больший объем информации (большая часть которого по-прежнему хранится в файлах). Эти файлы требуют организованного хранения и управления.
- Сейчас широко распространено не менее 5 основных облачных хранилищ (причем каждое обладает своими преимуществами):
— Google Drive — интеграция со всеми сервисами Google, распространено среди коллег (людей, с которыми часто приходится обмениваться информацией), удобный облачный офис;
— DropBox — распространено среди коллег;
— SkyDrive — распространено среди коллег, удобный облачный офис для работы с документами MS Office;
— Яндекс.Диск — (UPD) подарили навсегда 200 Гб за ошибку в одной из версий десктопного клиента, подарили 2 Гб на 2014 год;
— Облако.Mail.ru — подарили 1 Тб навсегда. - Файлы единой организованной структуры не могут быть размещены в одном облаке под двум причинам:
— бесплатные объемы недостаточны, и чем больше бесплатный объем тем беднее функционал и качество работы сервиса,
— предпочтения коллег также накладывают серьезные ограничения (по одному проекту могут быть одновременно файлы совместно редактируемые на Google Drive и SkyDrive, общие папки на DropBox). - Операционные системы
— десктоп: Windows 8.1,
— смартфон и планшет: Android 4.4. - Имею несколько мест работы, готовлюсь к поступлению в аспирантуру, файловый архив “коплю” уже около 15 лет, то есть информации, с которой приходится работать, достаточно много.
- Это вопрос, который так или иначе вынуждены решать для себя все, и все явно чувствуют несовершенство получаемых решений. В большой степени статья вдохновлена нижеследующими тщетными поисками:
— habrahabr.ru/post/68092
— habrahabr.ru/post/90326 - Сложность, трудоемкость, необходимость высокой квалификации не приветствуются.
Вариант решения
Файловая структура
Мне кажется, для организации хранения файлов уместна следующая классификация данных (файлов).
- Хранить вечно, доступ в будущем не предполагается. Эта категория данных, которую я называю “архивом”. Туда попадают документы “для истории”, которые в обозримом будущем нужны не будут, но когда-нибудь будут представлять “историческую ценность”.
- Хранить вечно, доступ в будущем очень вероятен. Это данные, относящиеся к категории постоянного (перманентного) хранения, доступ к таким данным периодически необходим. Это могут быть книги, музыка, дистрибутивы, сканы личных документов (паспорт, ИНН, прочее) и что угодно еще.
- Срок хранения не определен, доступ в будущем необходим. Это категория файлов проектов и “входящих” (в терминах GTD). Файлы разделены по папкам, каждая из которых соответствует одному проекту (в терминах GTD), и конечно отдельная папка для “входящих”.
Такое разделение данных позволяет четко понимать, что необходимо “старательно” бэкапить и что, в случае отсутствия потерь данных, будет доступно мне в любой момент в будущем.
Также важно, чтобы данное разделение данных было реализовано на одном уровне папок (без вложений), зачем это нужно — будет понятно из следующего раздела.
Структура каталогов, к которой я пришел, выглядит так (назовем ее базовой структурой каталогов):
Использование облачных хранилищ
Для унификации структуры хранения данных в каждом из облаков следует создать базовую структуру каталогов (если на данном облаке, например, файлы по проекту Х не хранятся, папку проекта можно не создавать, то же относится к архивам и данным постоянного хранения). После этого становится легко понятным — где именно в том или ином облаке сохранять данные, например, по тому или иному проекту.
Для удобства представления данных на компьютере базовую структуру каталогов (не обязательно полностью, по необходимости) предлагается реализовать на уровне библиотек Windows (про библиотеки можно почитать здесь: www.outsidethebox.ms/15096). Именно для этого базовая структура папок должна быть одноуровневой. Библиотеки отображают файлы, расположенные в нескольких папках на диске, и позволяют удобно управлять ими. Кроме того полезно создать библиотеку “Облака”, отображающую содержимое корневых папок всех используемых облачных хранилищ (в этой библиотеке будет несколько папок с одним именем — по одной из каждого облачного хранилища).
Удобны два представления библиотеки:
- “Общие элементы”. Все содержимое папок библиотеки выводится в единой таблице, без группировки по папке библиотеки (в нашем случае по облачному хранилищу).
- “Видео”. Содержимое библиотеки разбито по папкам библиотеки (облачным хранилищам), и представлено в виде крупных значков.
Теперь, работая с проектом, файлы по которому находятся в нескольких облачных хранилищах, достаточно войти в библиотеку проекта, и все файлы будут доступны для работы. Например, это может выглядеть так:
Библиотеки как инструмент крайне просты и удобны для централизованного управления облачными хранилищами и переброски файлов из одного облака в другое буквально в один клик.
Кстати, не все файлы нужно хранить на диске (объем доступного пространства в облачных хранилищах как правило больше объема физического диска). Например, папки “permanent_video” и “permanent_music” я вообще не синхронизирую с компьютером, а обмен с этими папками осуществляю через папку “temp” соответствующего облачного хранилища. Посмотрев какое-то видео, если я хочу сохранить его в облаке, я перемещаю его в папку “temp”, а затем через веб-интерфейс облака перемещаю файл в папку “permanent_video” — файл удаляется с диска компьютера, но сохраняется в облаке.
И еще одна небольшая “фишка”. Расположение папки “Рабочий стол” я перенастроил на папку “temp” в моем основном облаке (Google Drive), в эту же папку по умолчанию сохраняются все файлы, скачиваемые через браузер и торрент-клиент. Таким образом все новые файлы автоматически оказываются в одном единственном месте и сразу же попадают в облако.
Изложенное в статье, конечно же, не претендует ни на полноту, ни на абсолютную истинность, но, смею надеяться, может быть полезно читателям для организации собственной системы хранения файлов.
Источник
Хранение большого количества файлов
Доброго здравия, Хабражители! В процессе работы над проектом сайта знакомств возникла необходимость организовать хранение фотографий пользователей. По условиям ТЗ количество фотографий одного пользователя ограничено 10 файлами. Но пользователей-то могут быть десятки тысяч. Особенно учитывая то, что проект в его нынешнем виде существует аж с начала «нулевых». То есть там уже тысячи пользователей в базе. Почти любая файловая система, насколько мне известно, очень негативно реагирует на большое количество дочерних узлов в папке. По опыту могу сказать, что проблемы начинаются уже после 1000-1500 файлов/папок в родительской папке.
Дисклеймер. Я погуглил перед написанием статьи и обнаружил несколько решений обсуждаемого вопроса (например, тут или тут). Но не нашёл ни одного решения, в точности соответствующего моему. Кроме того, в данной статье я лишь делюсь собственным опытом решения задачи.
Теория
Помимо как таковой задачи хранения было ещё условие в ТЗ, согласно которому нужна была возможность оставлять к фотографиям подписи и заголовки. Само собой, без БД тут не обойтись. То есть первое, что мы делаем — это создаём таблицу, в которой прописываем сопоставление мета-данных (подписи, тайтлы и т.п.) с файлами на диске. Каждому файлу соответствует одна строка в БД. Соответственно, у каждого файла есть идентификатор.
Небольшое отступление. Поговорим про автоинкремент. На сайте знакомств может быть и десяток-другой тысяч пользователей. Вопрос в том, сколько вообще пользователей проходит через проект за всё время его существования. Например, активная аудитория «датинг-ру» составляет несколько сотен тысяч. Однако, только вообразите себе сколько пользователей удалилось за время жизни этого проекта; сколько пользователей не активировано до сих пор. А теперь приплюсуйте наше законодательство, обязывающее хранить информацию о пользователях не менее полугода… Рано или поздно 4 с копейками миллиарда UNSIGNED INT закончатся. По сему лучше всего для primary-ключа брать BIGINT.
А теперь попробуем представить себе число типа BIGINT. Это 8 байт. Каждый байт — это от 0 до 255. 255 дочерних нод — это вполне нормально для любой файловой системы. То есть берём идентификатор файла в шестнадцатеричном представлении, разбиваем оное на чанки по два символа. Используем эти чанки, как названия папок, причём последний в качестве имени физического файла. PROFIT!
Элегантно и просто. Расширение файла тут не принципиально. Всё равно файл будет отдаваться скриптом, который будет отдавать браузеру в частности MIME-тип, который мы тоже будем хранить в базе. Кроме того, хранение информации о файле в базе позволяет переопределять путь к нему для браузера. Скажем, файл у нас реально расположен относительно каталога проекта по пути /content/files/0f/65/84/10/67/68/19/ff.file . А в базе можно прописать ему URL, например, /content/users/678/files/somefile . SEO-шники сейчас, наверное, довольно улыбнулись. Всё это позволяет нам не беспокоиться больше о том, где размещать файл физически.
Таблица в БД
Помимо идентификатора, MIME-типа, URL и физического расположения мы будем хранить в таблице md5 и sha1 файлов для отсеивания одинаковых файлов при необходимости. Само собой нам нужно также хранить в этой таблице связи с сущностями. Допустим, ID пользователя, к которому относятся файлы. А если проект не шибко большой, то в той же системе мы можем хранить, скажем, фотографии товаров. По сему будем также хранить название класса сущности, к которой относится запись.
Кстати, о птичках. Если закрыть папку при помощи .htaccess для доступа извне, то файл можно будет получить только через скрипт. А в скрипте можно будет определить доступ к файлу. Немного забегая вперёд, скажу, что в моей CMS (на которой сейчас и пилится вышеупомянутый проект) доступ определяется базовыми пользовательскими группами, коих у меня 8 — гости, пользователи, менеджеры, админы, неактивированные, заблокированные, удалённые и супер-админы. Супер-админу можно абсолютно всё, так что его в определении доступа оный не участвует. Если есть у юзера флаг супер-админа, значит он супер-админ. Всё просто. То есть определять доступы будем оставшимся семи группам. Доступ простой — либо отдавать файл, либо не отдавать. Итого можно взять поле типа TINYINT.
И ещё один момент. Согласно нашему законодательству нам придётся физически хранить пользовательские картинки. То есть нам нужно как-то помечать картинки, как удалённые, вместо физического удаления. Удобнее всего для этих целей использовать битовое поле. Я обычно в таких случаях использую поле типа INT. Чтобы с запасом, так сказать. Притом у меня есть уже устоявшаяся традиция размещать флаг DELETED в 5-м бите с конца. Но это не принципиально опять таки же.
Что мы имеем в итоге:
Класс-диспетчер
Теперь нам нужно создать класс, при помощи которого мы будем файлы загружать. Класс должен обеспечивать возможность создавать файлы, заменять/изменять файлы, удалять файлы. Кроме того, стоит учесть два момента. Во-первых, проект может быть перенесён с сервера на сервер. Значит в классе нужно определить свойство, содержащее корневую директорию файлов. Во-вторых, будет очень неприятно, если кто-нибудь грохнет таблицу в БД. Значит нужно предусмотреть возможность восстановления данных. С первым всё в общем-то понятно. Что же касается резервирования данных, то резервировать мы будем только то, что нельзя восстановить.
ID — восстанавливается из физического расположения файла
entity_type — не восстанавливается
entity — не восстанавливается
mime — восстанавливается при помощи расширения finfo
md5 — восстанавливается из самого файла
sha1 — восстанавливается из самого файла
file — восстанавливается из физического расположения файла
url — не восстанавливается
meta — не восстанавливается
size — восстанавливается из самого файла
created — можно взять информацию из файла
updated — можно взять информацию из файла
access — не восстанавливается
flags — не восстанавливается
Сразу можно отбросить мета-информацию. Она не критична для функционирования системы. И для более оперативного восстановления всё же нужно сохранять MIME-тип. Итого: тип сущности, ID сущности, MIME, URL, доступ и флаги. Дабы повысить надёжность системы, будем хранить резервную информацию по каждой конечной папке отдельно в самой папке.
Рассмотрим некоторые моменты:
— realRoot — полный путь до папки с файловой системой оканчивающийся слешем.
— webRoot — путь от корня сайта без ведущего слеша (ниже увидите почему).
— В качестве СУБД я использую расширение MySQLi.
— По сути в метод upload первым аргументом передаётся информация из массива $_FILES.
— Если при вызове метода update передать ID существующего файла, он будет заменён, если в tmp_name входного массива будет непустым.
— Удалять и менять флаги файлов можно сразу по несколько штук. Для этого нужно передать вместо идентификатора файла либо массив с идентификаторами, либо строку с оными через запятую.
Маршрутизация
Собственно всё сводится к нескольким строчкам в htaccess в корне сайта (подразумевается, что mod_rewrite включен):
«content» — это папка в корне сайта в моём случае. Само собой Вы можете назвать папку по-другому. Ну и конечно же сам index.php, хранящийся в моём случае в папке content:
Ну и само собой закроем саму файловую систему от внешнего доступа. Положим в корень папки content/files файл .htaccess с одной лишь строчкой:
Источник
Оптимальный способ хранения большого количества файлов на сервере
Как известно в одной папке не стоит хранить большое количество файлов т.к. очень быстро может произойти сбой в системе или попросту файлы будут очень медленно считываться.
Для решения этой задачи многие программисты берут md5 имени файла f789f789abc898d6892df98d09a8f8, после чего разбивают имя примерно таким образом:
/f7/89/f789abc898d6892df98d09a8f8.jpg
Математика тут очень проста — один символ это 16 вариантов.
Таким образом 2 символа это уже 16*16=256 вариантов.
В нашем случае у нас 2 вложенности по 2 символа, таким образом максимальное количество папок будет 256*256=65536 папок.
Если нам потребуется сохранить 1000000 файлов то число файлов в каждой папке не превысит 1000000/65536=15 файлов.
Да, вариант прост, но что если нам требуется не только хорошо сохранять файлы, но и еще быстро их находить?
Например у нас социальная сеть и мы хотим для каждого пользователя создать отдельную папку с номером его id и хранить в ней файлы которые в свою очередь тоже имеют свой id.
И для нас важно не только сохранить файл но и быстро найти где он лежит по его id.
Для решения этой задачи я написал класс, который позволяет сохранять на сервере большое количество файлов или папок в древовидной структуре папок.
Вот какую структуру создает класс:
Чтобы посчитать максимально число файлов которое уместится в этой структуре нужно возвести максимальное количество файлов в папке в степень количества ветвей плюс один.
На изображении мы видим 2 ветви и по 3 файла в каждой папке.
Таким образом 3 нужно возвести в степень 2+1 = 3*3*3=27 файлов.
Для сохранения не более 1000000 файлов в такой структуре нам хватит 2 ветви по 100 файлов в каждой папке (100*100*100).
В класс нужно передать массив параметров — путь к папке где будет строиться дерево, максимальное число файлов в папке, число ветвей, либо можно применить паттерн (параметр pattern) максимального числа файлов, который уже был заранее просчитан — bigint, int, mediumint, smallint:
Для варианта социальной сети описанной выше, требуется 2 раза использовать класс: вначале для построения дерева папок, потом для построения в каждой папке дерева для файлов.
Так же обращаю ваше внимание, что в этом посте я опустил (а не не знал) тему «Максимально допустимое количество файлов на жестком диске».
Источник