Атрибут типа «Документ». Скачивание архива с файлами из таблицы и записи
Введение
Comindware Platform позволяет прикрепить любые файлы к атрибуту типа «Документ». При этом, если к атрибуту прикреплено несколько файлов, на форме и в таблице каждый файл приходится скачивать отдельно.
С помощью C#-скрипта можно настроить кнопку для скачивания в одном архиве всех файлов, прикреплённых к атрибуту.
Более того, можно скачать все файлы, прикреплённые к атрибуту, из нескольких записей, выбранных в таблице.
Здесь представлен пример настройки кнопки, скачивающей файлы из выбранных записей в таблице. Кроме того, на форме эта кнопка будет скачивать файлы, прикреплённые к атрибуту типа «Документ» в текущей записи.
См. также примеры работы с атрибутом типа «Документ»:
- Скачивание архива с файлами из всех строк таблицы с прикреплением архива к атрибуту
- Скачивание файлов в папку на сервере
- Клонирование записи вместе с прикреплёнными файлами
Структура атрибута типа «Документ»
- Атрибут типа «Документ» хранит одну или несколько ссылок на записи (документы) в системном шаблоне документа, к которым прикрепляются файлы (например, загруженные пользователями).
- В шаблоне документа имеется атрибут
currentRevision(текущая версия), который хранит ссылку на запись в системном шаблоне версии. - В шаблоне версии имеются атрибуты
title(имя) иcontent(содержимое), которые хранят имя файла и ссылку на файл, физически хранящийся в папкеStreamsна сервере.
Извлечение файлов из атрибута типа «Документ» с помощью C#
Чтобы считать файл из атрибута типа «Документ» с помощью C#-скрипта, необходимо:
-
из текущей записи получить массив идентификаторов файлов, прикреплённых к атрибуту:
var fileIds = Api.TeamNetwork.ObjectService.GetPropertyValues(recordId, new [] {"documentAttributeSystemName"})`; -
получить массив объектов с прикреплёнными файлами:
var attachedFileObjects = fileIds[docId].TryGetValue("Files", out object fileObject)&& fileObject != null ? fileObject as object[] : null; -
получить объект файла (
attachedFile):var attachedFile = Api.TeamNetwork.DocumentService.GetContent(attachedFileObject[0].ToString()); -
получить имя файла с расширением (
attachedFile.Name); - получить содержимое файла (
attachedFile.Data); -
при необходимости получить объект с метаданными документа:
var attachedFile = Api.TeamNetwork.DocumentService.GetDocument(attachedFileObject[0].ToString());attachedFile.Title— имя файла с расширением;attachedFile.Extension— расширение файла.
Прикладная задача
Имеется шаблон «Реестр документов», в котором хранятся файлы. Каждый документ может содержать несколько файлов.
В записи шаблона «Заявка» можно указать документы из «Реестра документов».
Пользователь должен иметь возможность скачать все файлы из всех выбранных строк в таблице на форме в заявке, из выбранных строк в «Реестре документов», а также на форме одного документа.
Настройка кнопки для скачивания файлов
Чтобы скачать документы, нужно настроить соответствующую кнопку и скрипт для неё.
- Создайте шаблон записи «Реестр документов».
-
Создайте следующие атрибуты:
Название Тип данных Свойства Наименование Текст Вложения Документ - Хранить несколько значений: флажок установлен
- Использовать для поиска записей: флажок установлен
Внимание!
Для корректного скачивания файлов с помощью C#-скрипта у атрибута типа «Документ» рекомендуется установить флажок «Использовать для поиска записей». В противном случае скрипт может не сработать.
-
Создайте кнопку «Скачать вложения» со следующими свойствами:
- Контекст операции: запись
- Операция: С# скрипт
- Результат выполнения: скачать документ
-
На вкладке «Скрипт» добавьте следующий C#-скрипт:
Скрипт для скачивания архива с файламиusing System;using System.Collections.Generic;using System.Linq;using Comindware.Data.Entity;using Comindware.TeamNetwork.Api.Data.UserCommands;using Comindware.TeamNetwork.Api.Data;using System.IO;using System.IO.Compression;class Script{public static UserCommandResult Main(UserCommandContext userCommandContext, Comindware.Entities entities){// ObjectIds — массив выбранных записей, полученный из контекста операции кнопки.var selected_Ids = userCommandContext.ObjectIds;// Создаем массив compressedBytes для хранения архива с файлами.byte[] compressedBytes;try{// Vlozheniya — системное имя атрибута «Вложения» шаблона записи «Реестр документов».// Помещаем в массив data значения атрибутов «Вложения» из выбранных записей.// Создаём поток resultStream для архиваvar data = Api.TeamNetwork.ObjectService.GetPropertyValues(selected_Ids, new[] { "Vlozheniya" });using (var resultStream = new MemoryStream()){using (var zip = new ZipArchive(resultStream, ZipArchiveMode.Update)){foreach (var id in selected_Ids){// Присваиваем переменной doc_Obj значение атрибута «Вложения».if (data[id].TryGetValue("Vlozheniya", out object doc_Obj) && doc_Obj != null){// Файлы из атрибута «Вложения» помещаем в массив doc_Array.// Проверяем, что количество файлов больше 0.var doc_Array = doc_Obj as object[];if(doc_Array.Length > 0){// Каждый файл в массиве doc_Array преобразуем в строку Base64// и помещаем в архив fileInArchive.foreach(var doc in doc_Array){var documentData = Api.TeamNetwork.DocumentService.GetContent(doc.ToString());var startStream = new MemoryStream();startStream.Write(documentData.Data, 0, documentData.Data.Length);startStream.Seek(0, SeekOrigin.Begin);var fileInArchive = zip.CreateEntry(documentData.Name, CompressionLevel.Optimal);using (var entryStream = fileInArchive.Open()){startStream.CopyTo(entryStream);}}}}}}// Помещаем поток с результирующим архивом в массив compressedBytes.compressedBytes = resultStream.ToArray();}// Создаём поток с результирующим архивомvar memStream = new MemoryStream(compressedBytes);// Помещаем поток с архивом в массив content.var content = memStream.ToArray();// Заполняем объект resulterr, который возвращает операция кнопки.var resulterr = new UserCommandResult{Success = true,Commited = true,// Собираем файл архива с именем ZipedFiles.zip и содержимым из массива content.// Этот файл скачает браузер после нажатия кнопки.File = new UserCommandFileResult(){Content = content,Name = "ZipedFiles.zip"},// Формируем сообщение об успешном выполнении операции кнопки.Messages = new[]{new UserCommandMessage{Severity = SeverityLevel.Normal,Text = "Успешно"}}};return resulterr;}// Обрабатываем любые ошибкиcatch{var resulterr = new UserCommandResult{Success = false,Commited = true,ResultType = UserCommandResultType.Notificate,Messages = new[]{new UserCommandMessage{Severity = SeverityLevel.Normal,Text = "Ошибка"}}};return resulterr;}}} -
Поместите атрибуты «Наименование» и «Вложения» в таблицу «Все записи» и на форму шаблона «Реестр документов».
- Поместите кнопку «Скачать вложения» в таблицу «Все записи» шаблона «Реестр документов».
-
В шаблоне записи «Заявка» создайте атрибут:
Название Тип данных Свойства Документы Запись - Связанный шаблон: Реестр документов
- Хранить несколько значений: флажок установлен
-
Поместите на форму шаблона «Заявка» атрибут «Документы» и настройте его представление в виде таблицы.
- Поместите в таблицу «Документы» на форме атрибуты «Наименование» и «Вложения» шаблона записи «Реестр документов».
- В область кнопок таблицы «Документы» поместите кнопки «Создать» и «Скачать вложения».
Тестирование
- Создайте новую запись шаблона «Заявка» и добавьте несколько строк с документами в таблицу «Документы».
- Выберите строки для скачивания документов и нажмите кнопку «Скачать вложения».
-
Браузер скачает архив с файлами, прикреплёнными к выбранным записям.
Примечание
Если в браузере отобразится сообщение «Незащищенное скачивание заблокировано», нажмите кнопку «Сохранить», чтобы продолжить скачивание.
-
Перейдите к таблице «Все записи» шаблона «Реестр документов».
- Выберите записи, из которых следует скачать вложения, и нажмите кнопку «Скачать вложения».
- Браузер скачает архив с файлами из выбранных записей.
- Откройте любую запись шаблона «Реестр документов» и нажмите кнопку «Скачать вложения».
-
Браузер скачает архив с файлами, прикреплёнными к записи.

Отображение кнопки «Скачать вложения» в таблице записей шаблона «Реестр документов»