File repository

Материал из Course Orchestra
Версия от 07:27, 29 мая 2017; D.trubachev (обсуждение | вклад) (Список функций)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск
Внимание! Вы просматриваете документацию к Celesta 6.x. Документация по Celesta 7.x доступна на courseorchestra.github.io/celesta.

1. Справочник Celesta

1.1 Введение и основные понятия
1.2 Запуск и авто-обновление
1.3 Базовая настройка
1.4 Системные таблицы
1.5 CelestaSQL
1.6 CelestaDoc
1.7 Контексты сессии и вызова
1.8 Курсоры
1.9 BLOB-поля
1.10 Option-поля
1.11 Защита от потерянных обновлений
1.12 Метаданные Celesta
1.13 CelestaUnit

2. Celesta и базы данных

2.1 Особенности работы Celesta с поддерживаемыми типами СУБД
2.2 Проектирование базы данных Celesta в DBSchema

3. Создание решений с использованием Celesta для ShowCase

3.1 Программа обучения Celesta
3.2 Подготовка рабочего места для работы с Celesta
3.2.1 Для разработчиков платформы
3.2.2 Для разработчиков решений
3.3 Системные гранулы Celesta
3.3.1 common
3.3.1.1 Экспорт/импорт данных
3.3.1.2 Навигатор
3.3.1.3 Серии номеров
3.3.1.4 Иерархия Дьюи
3.3.1.5 Системные функции
3.3.1.6 Реестр настроек
3.3.1.7 Mailsender
3.3.1.8 Common.filter
3.3.2 common.api
3.3.4 security
3.3.3 lyra
3.4 Стандартные гранулы Celesta
3.4.1 dirusing
3.4.2 workflow
3.4.3 File repository
3.5 Отрисовка элементов Showcase при помощи Celesta
3.5.1 Конвертер XML-JSON
3.5.2 Навигатор (Navigator)
3.5.3 Информационная панель (Datapanel)
3.5.4 Серверное действие (Server activity)
3.5.5 Вебтекст (WebText)
3.5.6 Грид (Grid)
3.5.6.1 Панель инструментов (ToolBar)
3.5.7 XForms
3.5.7.1 Селекторы
3.5.7.2 Submission
3.5.7.3 Загрузка/Выгрузка файлов (Upload/Download)

5. Решение проблем

5.1 Проблемы с кодировкой jython-файлов
Адрес на SVN: https://share.curs.ru/svn/grains/common.filerepository

Общая информация

Гранула fileRepository является системной и служит для хранения файлов внутри системы в обезличенном виде. Краткая информация о загруженном с помощью fileRepository файле такова:

1. В процессе подготовки перед началом работы необходимо добавить собственные настройки гранулы в файл grainsSettings, пример продемонстрирован в разделе Требования.

2. Перед загрузкой создаётся запись в таблице file схемы fileRepository.

3. Для каждой записи из таблицы file существует некоторое количество записей таблицы fileVersion. Записи таблицы fileVersion описывают местоположение файлов (смотри подробнее в главе Структура таблиц) и их текущий статус.

4. После создания отражающих операцию записей в таблицах, производится сама запись в БД. Скачивание файла осуществляется без изменений в БД.

Требования

При использовании гранулы file repository необходимым условием является на данный момент (05.02.2016) добавление настройки кластера в файл grainsSettings.xml под тег <grains>:

<grain name="fileRepository">
<!-- Лучше всего, чтобы путь к кластеру заканчивался папкой, оканчивающей на cluster. Почему? Потому что 
тогда это точно будет новая пустая папка. -->
<!-- Указывая кластер, будьте осторожны: функция создания структуры файлового хранилища удаляет всё внутри 
при первой инициализации. -->
    <clusterPath>
    <!-- Все 3 свойства кластера могут быть только числовыми! -->
	<cluster number="1" nestingSize="2" filesAmount="256">
        <!-- Адрес должен указывать либо на существующую директорию, либо располагаться в существующей 
             директории -->
	    D:\workspace\currentCluster
	</cluster>
    </clusterPath>

    <frSettings>
        <!-- Этот параметр указывает на то, надо ли создавать серию номеров: если false, то создаются. 
             После инициализации происходит автоматическая замена -->
        <parameter name="isSystemInitialised" value="false"></parameter>
    </frSettings>

</grain>

Пояснения: тег clusterPath объединяет под собой все кластеры, в которые может проводиться запись файлов; каждый тег cluster, как ясно из названия, представляет собой настройки кластера, где number есть порядковый номер кластера (главным и единственным требованием к нему является то, чтобы он был числовым и не повторяющимся), nestingSize определяет "глубину кластера" - то, сколько папок(директорий) лежит между самой папкой кластера и файлами, filesAmount определяет число папок/файлов в каждой директории.

Тег frSettings пока содержит лишь тег parameter, value которого обозначает, надо ли инициализировать серийные номера - если false, то инициализируем.

Для пользования интерфейсом Showcase для добавления / удаления / скачивания файлов (05.02.2016) необходимо добавить ссылку на хранилище в свою userdata:

<userdata name="%s">
    <group>navigatorFileRepository</group>
</userdata>

Структура таблиц

Таблицы расположены в схеме (грануле) fileRepository. Их три: file, fileVersion и fileCounter.




Таблица file :

Поля:
- id:
уникальный идентификатор, берущийся из numberSeries filesNS.
- name:
имя файла под которым он был загружен.
- uploadVersioning:
логическое значение, где True обозначает то, что предыдущие версии этого файла продолжают хранится после загрузки новой версии, ну 
и старые версии удаляются, если uploadVersioning == False.

Таблица fileVersion :

Поля:
- id:
уникальный идентификатор, берущийся из numberSeries fileVerNS.
- fileId:
id файла, версия которого была добавлена/изменена.
- clasterId:
id кластера, все данные о котором лежат в grainssettings.
- fileName:
имя файла внутри системы в числовом виде.
- versionMajor:
- versionMinor:
- exist:
если True, то файл существует и может быть скачен.
- timestamp:
время создания лога.

Таблица fileCounter :

Поля:
- clasterId:
уникальный идентификатор, указываемый в grainsSettings, при создании настройки кластера.
- latestFileName:
числовое имя последнего файла, загруженного в данный кластер.

Интерфейс Showcase

описание

Интерфейс прост и незамысловат: grid, выводящий список файлов и набор карточек, позволяющих добавить файл на сервер (без возможности при добавлении новых версий оставлять старые)(05.02.2016), перезаписать файл (то есть, загрузить один файл вместо другого с заменой названия), удалить файл (также удаляются записи в таблице fileVersion) и скачать с сервера. Эти возможности предоставляются посредством функций, лежащих в файлу functions.py и описаны ниже.

Список функций

Основные:

 putFile(context, native_filename, stream_input, current_cluster_num=1, rewritten_file_id=None, uploadVersioning=None):
     Происходит запись файла в кластер, путь к которому должен быть указан в grainSettings.xml и запись в БД о файле.
     Пояснения: native_filename - имя загружаемого файла, stream_input - входящий java поток, current_cluster_num - номер кластера, 
     в который следует положить файл, rewritten_file_id - если передаётся id файла, то его переписываем, uploadVersioning - если True, 
     то предыдущая версия файла не удаляется.
     Функция возвращает словарь вида:
        {
           "file_version_id": file_version_cursor.id,
           "file_id": file_cursor.id
        }


 downloadFile(context, file_id):
     Осуществляем загрузку файла последнего добавленного файла с данным file_id.
 deleteFile(context, file_id):
     Удаление файла из хранилища и всех упоминаний о нём в таблицах file и fileVersion.
 getFilePathById(context, file_id, file_version_id=None):
     Функция возвращает путь к последней версии файла либо к указанной

Примеры

Описание toolbar в grid:

def gridToolBar(context, main=None, add=None, filterinfo=None, session=None, elementId=None):
    u'''Toolbar для грида. '''
    session = json.loads(session)['sessioncontext']["related"]['gridContext']
    
    style = str('currentRecordId' not in session).lower()

    data = {
        "gridtoolbar": 
        {   "item":
            [
                { 
                      /* ... */
                                    "element": 
                                    {   
                                        "@id": "addFile",
                                        "add_context":"upload"
                                    }
                      /* ... */
                },{
                    "@img": 'gridToolBar/addDirectory.png',
                      /* ... */
                                    "element": 
                                    {   
                                        "@id": "addFile",
                                        "add_context":"replace"
                                    }
                      /* ... */
                    }
                },{
                      /* ... */
                                    "element": 
                                    {   
                                        "@id": "fileCardDelete",
                                        "add_context":"del"
                                    }
                      /* ... */
                    }
                },{
                    "@img": 'gridToolBar/arrowDown.png',
                    "@text":"Скачать файл",
                      /* ... */
                                    "element": 
                                    {   
                                        "@id": "fileCardDownload",
                                        "add_context":"download"
                                    }
                      /* ... */
                },
            ]
        }
    }

    return XMLJSONConverter.jsonToXml(json.dumps(data))

Обрабатывающие функции из карточки:

def cardDataSave(context, main=None, add=None, filterinfo=None, session=None, elementId=None, xformsdata=None):
    if add == 'del':
        # Порядок действий при удалении.
        session = json.loads(session)['sessioncontext']
        currId = session["related"]["gridContext"].get("selectedRecordId")
        functions.deleteFile(context, currId)

def cardUpload(context, main=None, add=None, filterinfo=None, session=None, elementId=None, data=None, fileName=None, file=None):
    session = json.loads(session)['sessioncontext']
    currId = session["related"]["gridContext"].get("selectedRecordId")
    # При добавлении файла в хранилище с помощью карточки, все необходимые параметры прилагаются.
    functions.putFile(context, fileName, file, rewritten_file_id=currId)
    

def cardDownload(context, main=None, add=None, filterinfo=None, session=None, elementId=None, data=None):
    session = json.loads(session)['sessioncontext']
    currId = session["related"]["gridContext"].get("selectedRecordId")
    # При скачивании же необходимо лишь указать id файла и передать подходящую карточку.   
    return functions.downloadFile(context, currId)

Активные элементы карточек (xforms) даны ниже:

<!-- Добавление файла в хранилище -->
<xf:upload id="xformId_cardUploadId" 
           filenamesMapping="XPath(instance(quot(xformId_mainInstance))/content/fileName)"
	   singleFile="true" 
           needClearFilenames="true"/>

<!-- Скачивание файла -->
<xf:trigger>
<xf:label>Скачать файл</xf:label>
    <xf:action ev:event="DOMActivate">
        <xf:load resource="javascript:gwtXFormDownload( 'xformId',
							'cardDownloadId',
							 Writer.toString(
                                                            getSubformInstanceDocument(	
                                                              'xformId_mainModel',
 							      'xformId_mainInstance'
                                                            ) 
                                                         )
         )"/>
    </xf:action>
</xf:trigger>


--S.gavrilov (обсуждение) 14:25, 20 февраля 2016 (UTC)