null

Работа со StreamedData на frontend

Содержание: 

0. Что важно знать o StreamedContent
1. Скачивание файлов через REST 
2. Проверка расширения файла
3. Сохранение в базу и скачивание из базы

4. Отображение картинки в jsf
5. Добавление кнопки для скачивания файла
6. Добавление кнопки для загрузки данных

 

Это вторая часть статьи про работу со StreamedCintent в java. В первой части были рассмотрены детали, касающиеся бэкенда, а в этой части будет разобрана фронтовая часть статьи (4-6 части содержания)

Для того, чтобы прочитать первую часть статьи, относящуюся к бэкенду можно перейти на первую часть этой статьи: https://www.tune-it.ru/web/marina/blog/-/blogs/rabota-so-streameddata-na-backend

 

4.  Отображение картинки в JSF

 

Отображать изображения можно при помощи тега  p:graphicImage в primefaces. В него достаточно передать сам стрим.

<p:graphicImage value="#{userBean.userPhoto}"
    rendered="#{userBean.userPhotoContentLength gt 0}"
    cache="false"               
    stream="false"
/>

Разберемся с представленными атрибутами: 


value - это метод для получения файла

rendered - правило для отображения контента. В нашем случае -- отображать картинку, если StreamedContent не пустой.

cache - управляет режимом кэширования ресурса браузером. По умолчанию true

stream - аттрибут, который может ввести в ступор, потому что мы передаем StreamedContent, который является стримом. Но на самом деле этот атрибут определяет, передается ли изображение в потоковом режиме или визуализируется напрямую как данные uri/base64 с поддержкой ViewScoped.
 

Остальные атрибуты можно посмотреть тут:
https://primefaces.github.io/primefaces/11_0_0/#/components/graphicimage?id=graphicimage
 

Сам бин при этом будет выглядеть так:

@Component
@Scope("view")

public class UserBean implements Serializable {

// Сервис для получение фотографии
@Autowired
privat AvatarService avatarService

// Массив данных изображения
private byte[] userPhotoBytes;
// Размер изображения
private int userPhotoContentLength;


// Пост-конструктор, в котором мы выгружаем изображение
@PostConstruct
private void init() {
   Long userId = getRequestParam(); // Опустим получение id пользователя, допустим, оно получается из параметра урла
  setPhoto(userId); // загрузим фото 
}

// Выгрузка фото и сохранения его в массив байтов
public void setPhoto(Long userId) {
      StreamedContent userPhoto = avatarService.getUserPhoto(userId);
       userPhotoBytes = userPhoto.getStream().readAllBytes();
       userPhotoContentLength = userPhoto.getContentLength();
}

// Getter для получения фото пользователя. Создается новый StreamedContent
public StreamedContent getUserPhoto() {
   return DefaultStreamedContent.builder()
           .stream(() -> new ByteArrayInputStream(userPhotoBytes))
           .contentLength(userPhotoContentLength)
           .contentType(userPhotoContentType)
           .build();
}

// Getter для получения размера изображения
Public int getUserPhotoContentLength() {
	return userPhotoContentLength;
}

}

 

5. Кнопка загрузки файла в JSF

 

Для того, чтобы загрузить файл можно воспользоваться p:fileUpload. Это файлаплоадер для загрузки файла через интерфейс.
 

Сам компонент будет выглядеть вот так: 

<p:fileUpload listener="#{fileUploadBean.upload}"
             label="Выбрать файл"
             update="@this"
             process="@this"
             allowTypes="/(\.|\/)(pdf|gif|jpe?g|png)$/"
             fileLimit="1"
             sizeLimit=10000
             required="true" 
             requiredMessage="Файл не был загружен"
             invalidFileMessage="Неверный тип файла"
             invalidSizeMessage="Файл слишком большой."
             fileLimitMessage="Вы не можете загрузить более одного файла"/>

 

Давайте пройдемся по его атрибутам:

listener - метод обработки для загрузки файла. Должен возвращать StreamedContent с файлом.

label - лэйбл для файлаплоадера.

update, process - какие компоненты надо апдейтить и процессить соответственно

allowTypes - паттерн для допустимых разрешений файлов. В примере - это pdf, gif, gpeg, jpg и png.

fileLimit - максимальное количество файлов

sizeLimit - максимальный размер файла в байтах

required - является ли загрузка файла обязательной

requiredMessage - сообщение об ошибке, в случае, если файл не загружен

invalidFileMessage - сообщение о неверном типе данных

invalidSizeMessage - сообщение о неверном размере файла

fileLimitMessage - сообщение о добавлении неверного количества файлов
 

Остальные атрибуты можно посмотреть тут:

https://primefaces.github.io/primefaces/11_0_0/#/components/fileupload?id=fileupload

 

FileUpload должен вызвать listener для загрузки файла. Этот метод принимает FileUploadEvent, который хранит сам файл. 

Напишем пример сохранения полученного файла:
 

@Autowired 
private FileRepository fileRepository;

public void upload(FileUploadEvent event) {
   UploadedFile uploadedFile = event.getFile();
if (uploadedFile == null) {
   log.info(“Файл не был загружен”);
   return;
}
	fileRepository = fileRepository.save(uploadedFile);
}

 

6. Кнопка скачивания файла JSF
 

Для того, чтобы создать кнопку скачивания файлов, необходимо создать саму кнопку. В примере ниже - это commandButton. И добавить туда fileDownload, в который необходимо передать файл для загрузки.

Пример:
 

<p:commandButton value="Скачать файл" ajax="false">
   <p:fileDownload value="#{fileDownloadBean.download}"/>
</p:commandButton>

 

Метод, который возвращает файл в бине выглядит так:
 

public StreamedContent download() {
   return DefaultStreamedContent.builder()
       .stream(() -> new ByteArrayInputStream(file.getContent()))
       .contentLength((int) file.contentLength())
       .contentType(StringUtil.safeToString(file.contentType()))
       .build();

}

 

Завершение:


Это все, что касается StreamedContent, что я хотела рассказать в рамках данных статей. 

Здесь был разобран поверхностный обзор того, как работать с этим типом данных на стороне backend и frontend
 

См. также:

Первая часть статьи [backend часть]: 
https://www.tune-it.ru/web/marina/blog/-/blogs/rabota-so-streameddata-na-backend

Документация к компонентам:

 

p:graphicImage:

https://primefaces.github.io/primefaces/11_0_0/#/components/graphicimage?id=graphicimage

p:fileUpload:

https://primefaces.github.io/primefaces/11_0_0/#/components/fileupload?id=fileupload

p:fileDownload:

https://primefaces.github.io/primefaces/11_0_0/#/components/filedownload?id=filedownload