Vaadin FileDropTarget表现糟糕

时间:2017-12-12 12:59:08

标签: java performance tomcat streaming vaadin8

我试图将Vaadin 8 FileDropTarget与Tomcat服务器一起使用。示例代码有点长,但它可能适合这里:

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;

import com.vaadin.server.StreamVariable;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Label;
import com.vaadin.ui.Notification;
import com.vaadin.ui.ProgressBar;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.dnd.FileDropTarget;

import hu.dynaxpress.base.mvc.DynaAbstractController;

@SuppressWarnings({ "serial", "rawtypes" })
public class FileStreamController extends DynaAbstractController {

    private VerticalLayout layout;
    private ProgressBar progress;

    @Override
    protected void onInit() {
        super.onInit();
        System.err.println("FileStreamController.onInit");
    }

    @Override
    protected void onEnter() {
        System.err.println("FileStreamController.onEnter");
        // https://vaadin.com/docs/v8/framework/components/components-upload.html

        layout = new VerticalLayout();

        final Label infoLabel = new Label("DROP A FILE ON THIS TEXT");
        infoLabel.setWidth(240.0f, Unit.PIXELS);        

        final VerticalLayout dropPane = new VerticalLayout(infoLabel);
        dropPane.setComponentAlignment(infoLabel, Alignment.MIDDLE_CENTER);
        dropPane.addStyleName("drop-area");
        dropPane.setSizeUndefined();
        dropPane.setWidth("100%");

        progress = new ProgressBar();
        progress.setIndeterminate(false);
        progress.setVisible(false);
        progress.setWidth("100%");
        dropPane.addComponent(progress);        
        layout.addComponent(dropPane);

        new FileDropTarget<>(dropPane, fileDropEvent -> {
            final long fileSizeLimit = 20 * 1024 * 1024 * 1024; // 20GB

            fileDropEvent.getFiles().forEach(html5File -> {
                // html5File.getFileSize() always returns zero, but why?
                if (false && ( html5File.getFileSize() > fileSizeLimit) ) {
                    Notification.show(
                            "File rejected. Max size=" +fileSizeLimit+ ", actual="+html5File.getFileSize(),
                            Notification.Type.WARNING_MESSAGE);
                } else {
                    Label lbl = new Label(html5File.getFileName() + " size=" + html5File.getFileSize() + " " + html5File.getType());
                    lbl.setWidth("100%");
                    layout.addComponent(lbl);
                    final StreamVariable streamVariable = new StreamVariable() {

                        @Override
                        public OutputStream getOutputStream() {
                            try {
                                return new FileOutputStream("F:\\"+html5File.getFileName());
                            } catch (FileNotFoundException e) {
                                e.printStackTrace();
                                throw new Error("F:\\"+html5File.getFileName());
                            } 
                        }

                        @Override
                        public boolean listenProgress() { return false; }

                        @Override
                        public void onProgress(final StreamingProgressEvent event) {
                            progress.setValue(
                                    event.getBytesReceived() / event.getContentLength()
                            );
                        }

                        @Override
                        public void streamingStarted(
                                final StreamingStartEvent event) {
                            progress.setVisible(true);
                            progress.setCaption(event.getFileName());
                        }

                        @Override
                        public void streamingFinished(
                                final StreamingEndEvent event) {
                            progress.setVisible(false);
                        }

                        @Override
                        public void streamingFailed(final StreamingErrorEvent event) {
                            progress.setVisible(false);
                        }

                        @Override
                        public boolean isInterrupted() { return false; }
                    };
                    html5File.setStreamVariable(streamVariable);
                    progress.setVisible(true);
                }
            });
        });

        setCompositionRoot(layout);     
    }


}

此代码有效,但它具有可怕的性能。在此MWE中,程序将所有删除的文件写入F:\驱动器。它是一个闪存驱动器(我想模拟流式大文件,看看随着时间的推移消耗了多少内存)。但是我发现这个程序在20秒内写出了一个40MB的文件。那是2MB / sec的速度。服务器在localhost上运行,源文件和目标F:驱动器都在我的本地计算机上。如果我只是将同一个文件复制到驱动器上,则只需不到2秒钟。

我也尝试过另一个(非常慢)的闪存驱动器,并且有类似的结果。当tomcat正在流式传输文件时,它的速度要慢10到20倍。

有没有办法让它更快?我究竟做错了什么?我没有看到任何加快速度的方法,因为流式传输发生在组件内部。

第二个重要(无相关)问题是为什么我无法获得文件大小?请参阅代码中的注释:&#34; html5File.getFileSize()始终返回零,但为什么?&#34;我从firefox调试器检查了POST头,浏览器在发送实际文件数据之前,在JSON / RPC调用中发送文件的大小。因此,服务器应该在第一个字节到达之前知道文件大小。

0 个答案:

没有答案