/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * Copyright (c) 2013, MPL CodeInside http://codeinside.ru */ package ru.codeinside.gses.activiti.ftarchive; import com.vaadin.terminal.DownloadStream; import com.vaadin.terminal.Sizeable; import com.vaadin.terminal.StreamResource; import com.vaadin.terminal.gwt.server.WebBrowser; import com.vaadin.ui.Button; import com.vaadin.ui.Component; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Label; import com.vaadin.ui.Link; import com.vaadin.ui.ProgressIndicator; import com.vaadin.ui.Upload; import com.vaadin.ui.Window; import commons.Streams; import ru.codeinside.gses.activiti.FileValue; import ru.codeinside.gses.service.Some; import ru.codeinside.gses.vaadin.customfield.CustomField; import ru.codeinside.gses.webui.Flash; import ru.codeinside.gses.webui.utils.Components; import javax.mail.internet.MimeUtility; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Serializable; import java.net.URI; final public class AttachmentField extends CustomField implements Serializable, Upload.Receiver { private static final long serialVersionUID = 1L; final Upload upload; final HorizontalLayout layout = new HorizontalLayout(); final ProgressIndicator indicator = new ProgressIndicator(); final Label sizeInfo = new Label(); Component oldValue; File tmpFile; Button removeAttachmentButton; final boolean signature; public AttachmentField(final String taskId, final String fieldId, final String name, FileValue attachment, boolean signature) { this.signature = signature; upload = new Upload(null, this); if (!signature) { upload.setButtonCaption("Выбрать файл"); upload.setImmediate(true); upload.addListener(new Upload.StartedListener() { private static final long serialVersionUID = 1L; @Override public void uploadStarted(Upload.StartedEvent event) { indicator.setValue(0f); indicator.setVisible(true); sizeInfo.setValue("0/" + event.getContentLength()); } }); upload.addListener(new Upload.ProgressListener() { private static final long serialVersionUID = 1L; public void updateProgress(long readBytes, long contentLength) { indicator.setValue((float) readBytes / (float) contentLength); sizeInfo.setValue("" + readBytes + "/" + contentLength); } }); upload.addListener(new Upload.SucceededListener() { private static final long serialVersionUID = 1L; @Override public void uploadSucceeded(Upload.SucceededEvent event) { removeOldValue(); String fileName = event.getFilename(); String fileType = event.getMIMEType(); FileValue value; if (taskId != null) { try { value = Flash.flash() .getExecutorService() .saveBytesBuffer(taskId, fieldId, fileName, fileType, tmpFile); } finally { tmpFile.delete(); } } else { value = new TmpFileValue(fileName, fileType, tmpFile); } setValue(value); setDownloadLink(createDownloadLink(value)); resetUpload(); } }); upload.addListener(new Upload.FailedListener() { private static final long serialVersionUID = 1L; @Override public void uploadFailed(Upload.FailedEvent event) { if (tmpFile != null) { tmpFile.delete(); tmpFile = null; } getWindow().showNotification("Ошибка при загрузке " + name, Window.Notification.TYPE_HUMANIZED_MESSAGE); } }); upload.addListener(new Upload.FinishedListener() { private static final long serialVersionUID = 1L; @Override public void uploadFinished(Upload.FinishedEvent event) { indicator.setVisible(false); sizeInfo.setValue(null); } }); indicator.setVisible(false); indicator.setWidth(100, Sizeable.UNITS_PIXELS); layout.setSpacing(true); layout.addComponent(indicator); layout.addComponent(sizeInfo); } setCaption(name); setValidationVisible(true); setRequiredError("Выберите файл!"); initRemoveAttachmentButton(); if (taskId != null) { Some<FileValue> optionalFile = Flash.flash().getExecutorService().getFileBuffer(taskId, fieldId); if (optionalFile.isPresent()) { FileValue newValue = optionalFile.get(); setValue(newValue); setDownloadLink(createDownloadLink(newValue)); } else { initAttachmentValue(attachment); } } else { initAttachmentValue(attachment); } if (!signature) { layout.addComponent(upload); layout.addComponent(removeAttachmentButton); } setCompositionRoot(layout); } private void initAttachmentValue(FileValue attachment) { if (attachment != null) { setValue(attachment, true); setDownloadLink(Components.createAttachShowButton(attachment, Flash.app())); } } void setDownloadLink(Component link) { oldValue = link; layout.addComponent(oldValue); if (!signature) { removeAttachmentButton.setVisible(true); upload.setVisible(false); } } private void initRemoveAttachmentButton() { if (!signature) { removeAttachmentButton = new Button("Удалить вложение"); removeAttachmentButton.setVisible(false); removeAttachmentButton.addListener(new Button.ClickListener() { @Override public void buttonClick(Button.ClickEvent event) { removeOldValue(); removeAttachmentButton.setVisible(false); upload.setVisible(true); setValue(null, true); resetUpload(); } }); } } void removeOldValue() { if (oldValue != null) { layout.removeComponent(oldValue); oldValue = null; } } @Override public Class<FileValue> getType() { return FileValue.class; } public OutputStream receiveUpload(String name, String type) { try { tmpFile = Streams.createTempFile("upload", ".tmp"); return new FileOutputStream(tmpFile); } catch (IOException e) { throw new RuntimeException("On upload " + name, e); } } @Override public void discard() throws SourceException { super.discard(); resetUpload(); } private void resetUpload() { sizeInfo.setValue(null); tmpFile = null; } Component createDownloadLink(final FileValue fileValue) { final Link result = new Link(); result.setCaption(fileValue.getFileName()); result.setTargetName("_top"); result.setImmediate(true); result.setDescription("Скачать"); StreamResource.StreamSource streamSource = new StreamResource.StreamSource() { public InputStream getStream() { return new ByteArrayInputStream(fileValue.getContent()); } }; StreamResource resource = new StreamResource(streamSource, fileValue.getFileName(), Flash.app()) { public DownloadStream getStream() { final StreamSource ss = getStreamSource(); if (ss == null) { return null; } final DownloadStream ds = new DownloadStream(ss.getStream(), getMIMEType(), getFilename()); ds.setCacheTime(0); try { WebBrowser browser = (WebBrowser) result.getWindow().getTerminal(); if (browser.isIE()) { URI uri = new URI(null, null, fileValue.getFileName(), null); ds.setParameter("Content-Disposition", "attachment; filename=" + uri.toASCIIString()); } else { ds.setParameter("Content-Disposition", "attachment; filename=\"" + MimeUtility.encodeWord(fileValue.getFileName(), "utf-8", "Q") + "\""); } } catch (Exception e) { ds.setParameter("Content-Disposition", "attachment; filename=" + fileValue.getFileName()); } return ds; } }; resource.setMIMEType(fileValue.getMimeType()); result.setResource(resource); return result; } }