Vaadin 上传文件流没有关闭?

Vaadin Upload filestream no close?

Vaadin 7.6.2

来自这个文档,来自这个代码示例: https://vaadin.com/docs/-/part/framework/components/components-upload.html

// Show uploaded file in this placeholder
final Embedded image = new Embedded("Uploaded Image");
image.setVisible(false);

// Implement both receiver that saves upload in a file and
// listener for successful upload
class ImageUploader implements Receiver, SucceededListener {
    public File file;

    public OutputStream receiveUpload(String filename,
                                      String mimeType) {
        // Create upload stream
        FileOutputStream fos = null; // Stream to write to
        try {
            // Open the file for writing.
            file = new File("/tmp/uploads/" + filename);
            fos = new FileOutputStream(file);
        } catch (final java.io.FileNotFoundException e) {
            new Notification("Could not open file<br/>",
                             e.getMessage(),
                             Notification.Type.ERROR_MESSAGE)
                .show(Page.getCurrent());
            return null;
        }
        return fos; // Return the output stream to write to
    }

    public void uploadSucceeded(SucceededEvent event) {
        // Show the uploaded file in the image viewer
        image.setVisible(true);
        image.setSource(new FileResource(file));
    }
};
ImageUploader receiver = new ImageUploader();

// Create the upload with a caption and set receiver later
Upload upload = new Upload("Upload Image Here", receiver);
upload.setButtonCaption("Start Upload");
upload.addSucceededListener(receiver);

// Put the components in a panel
Panel panel = new Panel("Cool Image Storage");
Layout panelContent = new VerticalLayout();
panelContent.addComponents(upload, image);
panel.setContent(panelContent);

关于这个我有几个问题:

  1. 为什么没有 fos.close() 任何地方(在 finally 块中)?
  2. 为什么 OutputStream 从方法返回?特别是当 receiver 被传递给一个监听器时?监听器是否正在关闭流?
  3. 在哪里关闭流?

如果您查看 sources,您会看到:

  1. Why no fos.close() anywhere (in finally block)?

因为关闭输出流不是由你决定的。该框架将处理读取它接收到的数据,将其写入文件并关闭流(即使出现问题)。这发生在 FileUploadHandler in the streamToReceiver() method (line 529 in the current version).

  1. Why in the world is OutputStream returned from the method? Especially when the receiver is being passed into a Listener? Is the Listener closing the stream?

因为 Receiver 的唯一目的是告诉框架应该将接收到的数据写入何处。来自文档:

/**
 * Interface that must be implemented by the upload receivers to provide the
 * Upload component an output stream to write the uploaded data.
 *
 * @author Vaadin Ltd.
 * @since 3.0
 */

为了进一步阐明 receiver 被传递到 Listener 的混乱:它不是。 ImageUploader 实现了两者

因此,相同的 ImageUploader 实例被传递到 Upload 组件的构造函数中,它将被用作 Receiver,并在 addSucceededListener() 方法中传递它将用作……你猜对了,SucceededListener。大多数人(可能?!)更喜欢在同一个 class 中实现所有这些接口,但如果您愿意,您可以选择在它们自己的 class 中实现每个功能,然后传递一个每个方法的适当实例。

  1. Where do I close the stream?

你不需要,正如第 1 点所述,上传完成后框架会为你关闭它。同时,你可以去喝杯啤酒:-)