fileStorageUploadField 文件存储上传

fileStorageUploadField 支持用户将文件上传至 Jmix 文件存储

  • XML 元素:fileStorageUploadField

  • Java 类:FileStorageUploadField

基本用法

这个组件可以包含标题、已上传文件的链接和一个上传按钮。当点击上传按钮的时候,会弹出标准的文件选择器,用户可以在这里选择需要上传的文件。

file storage upload basics

fileStorageUploadField 既可以 绑定实体属性,也可以不绑定数据。

下面的示例我们展示在没有数据绑定的情况下使用组件。可以用来直接处理上传的文件,而无需将其与任何 Jmix 实体关联。

<fileStorageUploadField id="fileRefField"
                        acceptedFileTypes=".xlsx, .xls"
                        fileStoragePutMode="MANUAL"
                        fileNameVisible="true"/>

可以直接在 FileUploadSucceededEvent 事件中处理上传的文件。

如需以字节数组的格式在实体属性保存文件,而不是 FileRef,那么请使用 fileUploadField 组件。

如需同时上传多个文件,请使用 upload 组件。

上传的文件会立即保存在默认的 FileStorage 中。如需以编程的方式控制文件的存储,可以使用 fileStoragePutMode 属性。

数据绑定

fileStorageUploadField 支持用户上传文件至 文件存储 并作为一个 FileRef 对象设置给实体属性。

下面例子中,User 实体的 picture 属性是 FileRef 类型。

@Column(name = "PICTURE", length = 1024)
private FileRef picture;
<data>
    <instance class="com.company.onboarding.entity.User" id="userDc">
        <fetchPlan extends="_base"/>
        <loader id="userDl"/>
    </instance>
</data>
<layout>
    <fileStorageUploadField dataContainer="userDc"
                            property="picture"
                            clearButtonVisible="true"
                            fileNameVisible="true"/>
</layout>

fileStorageUploadFielddataContainer 属性指定连接的数据容器;property 属性指定展示在 fileStorageUploadField 的实体属性名。

国际化

fileStorageUploadField 的所有标签和消息都可以配置。

file storage upload text attrs
  1. label 属性。

  2. uploadText 属性。

  3. requiredMessage 属性。

  4. fileNotSelectedText 属性。

  5. helperText 属性。

  6. fileTooBigText 属性。

  7. incorrectFileTypeText 属性。

  8. uploadDialogTitle 属性。

  9. remainingTimeText 属性。

  10. uploadDialogCancelText 属性。

  11. processingStatusText 属性。

connectingStatusText

设置当连接建立后在上传窗口展示的状态文本。

该属性可以是文本本身或者 消息包 中的一个键值。如果是消息包键值,则必须以 msg:// 开头。

fileNotSelectedText

设置当 fileNameVisible="true" 而文件还未上传时显示的文本。默认显示 "File is not selected(未选择文件)"。

该属性可以是文本本身或者 消息包 中的一个键值。如果是消息包键值,则必须以 msg:// 开头。

fileTooBigText

设置当文件大小超出 maxFileSize 设置的值后异常信息的文本。

该属性可以是文本本身或者 消息包 中的一个键值。如果是消息包键值,则必须以 msg:// 开头。

incorrectFileTypeText

设置当文件扩展名不包含在 acceptedFileTypes 属性时显示的消息。

该属性可以是文本本身或者 消息包 中的一个键值。如果是消息包键值,则必须以 msg:// 开头。

processingStatusText

设置当文件上传成功且处理完成后显示在上传窗口的状态文本。

该属性可以是文本本身或者 消息包 中的一个键值。如果是消息包键值,则必须以 msg:// 开头。

remainingTimeText

设置显示上传弹窗中剩余上传时间的文本。

该属性可以是文本本身或者 消息包 中的一个键值。如果是消息包键值,则必须以 msg:// 开头。

remainingTimeUnknownText

设置当无法计算剩余上传时间时上传弹窗中显示的文本。

该属性可以是文本本身或者 消息包 中的一个键值。如果是消息包键值,则必须以 msg:// 开头。

uploadDialogCancelText

设置上传弹窗中取消按钮的显示文本。

该属性可以是文本本身或者 消息包 中的一个键值。如果是消息包键值,则必须以 msg:// 开头。

uploadDialogTitle

设置当正在上传文件时上传弹窗的标题。

该属性可以是文本本身或者 消息包 中的一个键值。如果是消息包键值,则必须以 msg:// 开头。

uploadText

设置上传按钮的文本。

该属性可以是文本本身或者 消息包 中的一个键值。如果是消息包键值,则必须以 msg:// 开头。

XML 属性

acceptedFileTypes

指定服务器能接收的文件类型。文件格式使用 MIME 类型模式 或文件扩展名定义。

MIME 类型具有广泛的支持,而文件扩展名仅在某些浏览器支持,因此需要尽可能避免使用扩展名。
<fileStorageUploadField dataContainer="userDc"
                        property="picture"
                        acceptedFileTypes="image/png, .png"/>
acceptedFileTypes 属性能过滤系统文件选择对话框中的文件类型,确保用户只能选择允许的类型。

clearButtonAriaLabel

MDN

设置清空按钮的 aria-label 属性。

clearButtonVisible

设置是否在文件名后面显示清除按钮。仅当 fileNameVisible="true" 有效。

默认值是 false

dropAllowed

设置组件是否支持拖放文件进行上传。

默认值是 true

文件只能被拖放至组件的 Upload 按钮上。

fileNameVisible

fileNameVisible 属性设置是否在上传按钮旁边显示上传的文件名称。默认为 false

fileStorageName

设置上传文件保存的 FileStorage 名称。如果未设置,则使用默认的文件存储。

fileStoragePutMode

设置文件放入文件存储的模式。fileStoragePutMode 属性默认设置为 IMMEDIATE。如果设置为 MANUAL 值,则能以编程的方式控制文件的保存:

<fileStorageUploadField id="manuallyControlledField"
                        dataContainer="userDc"
                        property="picture"
                        clearButtonVisible="true"
                        fileNameVisible="true"
                        fileStoragePutMode="MANUAL"/>

视图控制器中,定义组件和 TemporaryStorage 接口。然后订阅文件上传成功或出错的 事件

@Autowired
private TemporaryStorage temporaryStorage;
@ViewComponent
private FileStorageUploadField manuallyControlledField;
@Autowired
private Notifications notifications;

@Subscribe("manuallyControlledField")
public void onManuallyControlledFieldFileUploadSucceeded(
        final FileUploadSucceededEvent<FileStorageUploadField> event) {
    Receiver receiver = event.getReceiver();
    if (receiver instanceof FileTemporaryStorageBuffer) {
        UUID fileId = ((FileTemporaryStorageBuffer) receiver)
                .getFileData().getFileInfo().getId();
        File file = temporaryStorage.getFile(fileId);

        if (file != null) {
            notifications.create("File is uploaded to temporary storage at "
                            + file.getAbsolutePath())
                    .show();
        }
        FileRef fileRef = temporaryStorage.putFileIntoStorage(fileId, event.getFileName());
        manuallyControlledField.setValue(fileRef);
        notifications.create("Uploaded file: "
                        + ((FileTemporaryStorageBuffer) receiver).getFileData().getFileName())
                .show();
    }
}

该组件将文件上传至临时存储之后,便会调用 FileUploadSucceedEvent 的监听器。

TemporaryStorage.putFileIntoStorage() 方法将上传的文件从临时客户端存储移至默认的 文件存储

在上传具有 MANUAL 模式的 FileStorageUploadField 字段后,不会自动触发 ComponentValueChangeEvent,因为 FileRef 的值只能在文件上传至永久文件存储后获得。

maxFileSize

设置允许上传文件的最大字节数。注意,这是一个客户端层面的约束,会在发送上传请求至服务器之前检查。

如果 MultipartProperties 可用,则默认值取自 MultipartProperties#getMaxFileSize()(默认为 1MB)。

如需全局配置所有组件的最大支持文件大小,使用以下 Spring Boot 应用程序属性:

更多选项请参考 Spring Boot 文档。

这些属性适用于 JAR 部署。对于 WAR 部署,可能需要在应用服务器设置中配置文件大小限制。

uploadIcon

设置上传按钮的图标。

事件和处理器

在 Jmix Studio 生成处理器桩代码时,可以使用 Jmix UI 组件面板的 Handlers 标签页或者视图类顶部面板的 Generate Handler 添加,也可以通过 CodeGenerate 菜单(Alt+Insert / Cmd+N)生成。

FileUploadFailedEvent

当底层的 Upload 组件产生 FailedEvent 时,会发送 io.jmix.flowui.kit.component.upload.event.FileUploadFailedEvent

FailedEvent 表示文件已经被服务器接收,但是接收程序在完成之前中断。一般是由于网络原因、服务端处理出错或手动取消上传。

@Subscribe("manuallyControlledField")
public void onManuallyControlledFieldFileUploadFailed(
        final FileUploadFailedEvent<FileStorageUploadField> event) {
    notifications.create("File upload error")
            .show();
}

FileUploadFileRejectedEvent

当底层 Vaadin Upload 组件产生 FileRejectedEvent 时,会触发 io.jmix.flowui.kit.component.upload.event.FileUploadFileRejectedEvent 事件。

此事件表示用户选择的文件因未能满足上传组件上配置的一个或多个约束而被拒绝,例如:

当违反上传约束时,可以使用此事件向用户提供反馈。

FileUploadFinishedEvent

当底层 Vaadin Upload 组件产生 FinishedEvent 时,会触发 io.jmix.flowui.kit.component.upload.event.FileUploadFinishedEvent 事件。

此事件表示文件上传过程已完成,无论其结果如何。无论是成功上传还是失败的尝试,都会触发该事件。

要更精细地控制上传结果,请考虑使用以下特定的子事件:

FileUploadProgressEvent

在底层 Vaadin Upload 组件发出 ProgressUpdateEvent 时触发 io.jmix.flowui.kit.component.upload.event.FileUploadProgressEvent 事件。

此事件支持实时跟踪正在上传的文件,并提供关于上传进度的连续反馈,可以更新 UI 元素。

FileUploadStartedEvent

在底层 Vaadin Upload 组件发出 StartedEvent 时触发 io.jmix.flowui.kit.component.upload.event.FileUploadStartedEvent 事件。

此事件表示文件上传过程的开始,即在用户选择文件并启动向服务器的传输后立即触发。

FileUploadSucceededEvent

在底层 Vaadin Upload 组件触发 SucceededEvent 时触发 io.jmix.flowui.kit.component.upload.event.FileUploadSucceededEvent 事件。

此事件确认文件上传已成功完成,表示文件已被服务器完全接收且处理无误。

下面是使用 fileStorageUploadField 上传 .xls.xlsx 文件的示例,文件在 FileUploadSucceededEvent 事件中处理。

@Subscribe("fileRefField")
public void onFileRefFieldFileUploadSucceeded(
        final FileUploadSucceededEvent<FileStorageUploadField> event) {
    if (event.getReceiver() instanceof FileTemporaryStorageBuffer buffer) {
        UUID fileId = buffer.getFileData().getFileInfo().getId();
        log.info("FileId: " + fileId);

        File file = temporaryStorage.getFile(fileId); (1)
        log.info("File from temp storage: " + file);
        try { (2)
            List<String> lines = FileUtils.readLines(file, StandardCharsets.UTF_8);
            for (String line : lines) {
                log.info("Read line: " + line);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        temporaryStorage.deleteFile(fileId); (3)
        log.info("File is deleted from temp storage: " + file);
    }
}
1 使用上传事件提供的 id 从 临时存储 获取文件。
2 处理文件数据。
3 删除上传的文件。在真实的应用程序中,这里可以使用 temporaryStorage.putFileIntoStorage() 方法将文件移至 FileStorage

fileStoragePutMode 的介绍中也有 FileUploadSucceededEvent 的示例。

XML 内部元素