3.5.2.1.17. 文件上传控件
FileUploadField
允许用户上传文件到服务器。这个控件包含标题 、 已上传文件的链接 、 还有两个按钮:上传按钮和清除文件选择按钮。当点击上传按钮的时候,会弹出系统标准的文件选择器,用户可以在这里选择需要上传的文件。如果是要上传多个文件,可以用 FileMultiUploadField 控件。
该控件对应的 XML 名称:upload
对于 FileDescriptor
类型的实体属性,可以在 FieldGroup 内用 datasource 属性使用此控件,也可以在 Form 中通过 dataContainer 属性使用,或者也能单独使用。如果此控件绑定到任何数据组件,上传的文件会被立即保存到文件存储,对应的 FileDescriptor
实例会保存到数据库。
<upload fileStoragePutMode="IMMEDIATE"
dataContainer="personDc"
property="photo"/>
还可以通过编程的方式控制文件和 FileDescriptor
的保存:
-
在界面的 XML 描述中声明这个控件:
<upload id="uploadField" fileStoragePutMode="MANUAL"/>
-
在界面控制器中,需要注入该控件本身,还需要注入 FileUploadingAPI 和 DataManager 这两个接口。然后,订阅上传成功或出错的事件:
@Inject private FileUploadField uploadField; @Inject private FileUploadingAPI fileUploadingAPI; @Inject private DataManager dataManager; @Inject private Notifications notifications; @Subscribe("uploadField") public void onUploadFieldFileUploadSucceed(FileUploadField.FileUploadSucceedEvent event) { File file = fileUploadingAPI.getFile(uploadField.getFileId()); (1) if (file != null) { notifications.create() .withCaption("File is uploaded to temporary storage at " + file.getAbsolutePath()) .show(); } FileDescriptor fd = uploadField.getFileDescriptor(); (2) try { fileUploadingAPI.putFileIntoStorage(uploadField.getFileId(), fd); (3) } catch (FileStorageException e) { throw new RuntimeException("Error saving file to FileStorage", e); } dataManager.commit(fd); (4) notifications.create() .withCaption("Uploaded file: " + uploadField.getFileName()) .show(); } @Subscribe("uploadField") public void onUploadFieldFileUploadError(UploadField.FileUploadErrorEvent event) { notifications.create() .withCaption("File upload error") .show(); }
1 | 此时如果需要的话,可以取到保存在临时存储的文件。 |
2 | 一般来说,文件需要保存到中间件的文件存储中。 |
3 | 将文件保存至 FileStorage。 |
4 | 将文件描述器保存到数据库。 |
该控件将所有选择的文件上传到客户端层 的临时存储(temporary storage)并且调用 FileUploadSucceedEvent
监听器。在这个监听器里面,从 uploadField 获取了一个 FileDescriptor
。com.haulmont.cuba.core.entity.FileDescriptor
(别跟 java.io.FileDescriptor
混淆了) 是一个持久化实体,唯一定义一个上传的文件,并且也用这个类从系统下载文件。
FileUploadingAPI.putFileIntoStorage()
方法把文件从客户端层的临时存储移动到文件存储。这个方法的参数是临时存储中文件的标识符和对应的 FileDescriptor
对象,这两个参数都是由 FileUploadField
提供的。
当上传文件到 FileStorage
完成后,通过调用 DataManager.commit()
把 FileDescriptor
实例存到数据库。这个方法会返回保存的实体,可以用来赋值给其它实体里关联这个文件的属性。这里只是简单的把 FileDescriptor
存到了数据库。从 Administration > External Files 界面可以看到这个文件。
FileUploadErrorEvent
监听器会在从客户端上传文件到临时存储出错的时候被调用。
以下是可以订阅的事件,用来跟踪上传进度:
-
AfterValueClearEvent
-
BeforeValueClearEvent
-
FileUploadErrorEvent
-
FileUploadFinishEvent
-
FileUploadStartEvent
-
FileUploadSucceedEvent
-
ValueChangeEvent
fileUploadField
的属性:
-
fileStoragePutMode
- 定义文件和相应的FileDescriptor
怎么存储。-
IMMEDIATE
模式,在文件存到客户端层临时存储之后立即存储。 -
MANUAL
模式, 需要手动在FileUploadSucceedListener
里面编码实现。当在
FieldGroup
里面使用FileUploadField
的时候,默认模式是IMMEDIATE
,其它情况下,默认模式是MANUAL
。
-
-
uploadButtonCaption
、uploadButtonIcon
和uploadButtonDescription
这三个 XML 属性可以设置上传按钮的属性。
-
showFileName
- 控制上传文件的名称是否要显示在上传按钮旁边,默认是false
不显示。
-
showClearButton
- 控制是否要显示清空按钮,默认false
不显示。
-
clearButtonCaption
、clearButtonIcon
和clearButtonDescription
这三个 XML 属性可以设置清空按钮的属性。
-
accept
XML 属性 (或者相应的setAccept()
方法) 用来设置文件选择对话框里面的文件类型掩码,但是用户还是可以选择“所有文件”来上传任意文件。这个属性的值需要是以英文逗号分隔的文件扩展名,比如:
*.jpg,*.png
。 -
最大可上传的文件大小是由 cuba.maxUploadSizeMb 应用程序属性定义的,默认是 20MB。如果用户选择了更大的文件的话,会有相应的提示信息,并且中断上传过程。
-
fileSizeLimit
XML 属性 (或者相应的setFileSizeLimit()
方法) 用来设置最大允许上传的文件大小,以字节为单位。<upload id="uploadField" fileSizeLimit="2000"/>
-
permittedExtensions
XML 属性 (或者相应的setPermittedExtensions()
方法) 设置允许的文件扩展名白名单。这个属性的值需要是字符串的集合,其中每个字符串是以
.
开头的允许的文件扩展名,比如:uploadField.setPermittedExtensions(Sets.newHashSet(".png", ".jpg"));
-
dropZone
- 允许设置一个特殊的 BoxLayout 用来作为从浏览器外部拖拽文件可以放置的目标容器区域。这个目标区域可以覆盖整个对话框的窗口。当文件被拖拽到这块区域的时候,这个容器会被高亮显示,否则目标区域不会显示。<layout spacing="true" width="100%"> <vbox id="dropZone" height="AUTO" spacing="true"> <textField id="textField" caption="Title" width="100%"/> <textArea id="textArea" caption="Description" width="100%" rows="5"/> <checkBox caption="Is reference document" width="100%"/> <upload id="upload" dropZone="dropZone" showClearButton="true" showFileName="true"/> </vbox> <hbox spacing="true"> <button caption="mainMsg://actions.Apply"/> <button caption="mainMsg://actions.Cancel"/> </hbox> </layout>
如果想要 dropZone 不变并且一直显示,需要给这个容器设置预定义的样式名称
dropzone-container
。此时这个容器应该是空的,只包含一个label
组件:<layout spacing="true" width="100%"> <textField id="textField" caption="Title" width="100%"/> <checkBox caption="Is reference document" width="100%"/> <upload id="upload" dropZone="dropZone" showClearButton="true" showFileName="true"/> <vbox id="dropZone" height="150px" spacing="true" stylename="dropzone-container"> <label stylename="dropzone-description" value="Drop file here" align="MIDDLE_CENTER"/> </vbox> <hbox spacing="true"> <button caption="mainMsg://actions.Apply"/> <button caption="mainMsg://actions.Cancel"/> </hbox> </layout>
-
pasteZone
允许设置一个特殊的容器用来处理粘贴(paste)的快捷键。此时需要这个容器内部的一个文字输入控件获得焦点(focused)。这个功能只支持基于 Chromium 的浏览器。<upload id="uploadField" pasteZone="vboxId" showClearButton="true" showFileName="true"/>
参考 在 CUBA 应用程序中使用图片 指南,了解上传文件的一些更加复杂的示例。
- upload 的属性
-
accept - align - caption - captionAsHtml - clearButtonCaption - clearButtonDescription - clearButtonIcon - contextHelpText - contextHelpTextHtmlEnabled - css - dataContainer - description - descriptionAsHtml - dropZone - editable - enable - box.expandRatio - fileSizeLimit - fileStoragePutMode - height - htmlSanitizerEnabled - icon - id - pasteZone - permittedExtensions - property - showClearButton - showFileName - stylename - tabIndex - uploadButtonCaption - uploadButtonDescription - uploadButtonIcon - visible - width
- API
-
addValueChangeListener - commit - discard - isModified - setContextHelpIconClickHandler
- upload 事件
-
AfterValueClearEvent - BeforeValueClearEvent - FileUploadErrorEvent - FileUploadFinishEvent - FileUploadStartEvent - FileUploadSucceedEvent - ValueChangeEvent