文章目录
- 前言
- 一、开发Action
- 1. 修改Table
- 2. BDEF中新增Action
- 3. 新建结构,用于接收uuid以及附件数据
- 4. 实现Method逻辑
- 二、UI5项目修改
- 1. 添加表格行
- 2. 事件处理函数
- 3. 点击文件名时的事件
- 三、测试
前言
这系列文章详细记录在Fiori应用中如何在前端和后端之间使用文件进行交互。
这篇的主要内容有:
- 后端RAP的开发(S4HANA On-Premise)
- 新建Action(保存base64)
- 前端(UI5)读取文件并保存到后端
- 传输文件流,并保存在ABAP数据库表
- 在前端下载已保存的文件
- 在前端显示已保存的图片
一、开发Action
1. 修改Table
- 新增3个字段 attachment ,filename,filetype
- 对应的CDS也添加三个字段
define table ymoon_t010 {key client : abap.clnt not null;key uuid : sysuuid_x16 not null;name : abap.char(40);age : abap.int1;gender : abap.char(10);city : abap.char(40);attachment : abap.string(0);filename : abap.char(100);filetype : abap.char(100);}
2. BDEF中新增Action
managed implementation in class zbp_moon_i_010 unique;
strict ( 2 );define behavior for ymoon_i_010 alias Student
persistent table YMOON_T010
early numbering
lock master
authorization master ( instance )
//etag master <field_name>
{create;update;delete;//Add Actionstatic action upload_file parameter ymoon_s010;//新增Actionstatic action upload_attachment parameter ymoon_s011;}
3. 新建结构,用于接收uuid以及附件数据
@EndUserText.label : 'uuid & Attachment'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
define structure ymoon_s011 {uuid : sysuuid_x16;attachment : abap.string(0);filename : abap.string(0);
}
4. 实现Method逻辑
这里把base64保存到string类型中
method upload_attachment."获取UI5传送的parameterdata(uuid) = keys[ 1 ]-%param-uuid.data(attachment) = keys[ 1 ]-%param-attachment.data(filename_full) = keys[ 1 ]-%param-filename."split filename_full at `.` into data(lv_filename) data(lv_filetype)."更新update ymoon_t010set filename = lv_filenamefiletype = lv_filetypeattachment = attachmentwhere uuid = uuid.endmethod.
二、UI5项目修改
1. 添加表格行
- 新增附件和文件名列, 并使用FileUploader和Link组成cell
<columns><Column><Text text="姓名" /></Column><Column><Text text="年龄" /></Column><Column><Text text="性别" /></Column><Column><Text text="城市" /></Column><Column><Text text="选择附件" /></Column><Column><Text text="文件名" /></Column>
</columns>
<items><ColumnListItem><cells><Text text="{Name}" /><Text text="{Age}" /><Text text="{Gender}" /><Text text="{City}" /><u:FileUploaderid="Attachment"name="Attachment"tooltip="Upload your Attachment to the server"buttonText="上传附件"change="onUploadAttachment"/><Link text="{= ${Filename} !== '' ? ${Filename} + '.' + ${Filetype} : ''}" /></cells></ColumnListItem>
</items>
2. 事件处理函数
- 上传文件时,获取当前行的uuid并调用Action传输到后端
onUploadAttachment: function (e) {// console.log(e)var oModel = this.getView().getModel();var file = e.getParameter("files")[0]var filename = e.getSource().getProperty('value')var uuid = e.getSource().getBindingContext().getProperty().Uuidvar reader = new FileReader();reader.onload = function (evt) {// 获取文件流var vContent = evt.currentTarget.result;oModel.callFunction("/upload_attachment", {method: "POST", urlParameters: { //参数,首字母大写 "Uuid": uuid,"Attachment": vContent,"Filename": filename},success: function (odata, response) {//Model RefreshMessageBox.information("附件上传成功! " + filename);oModel.refresh(true);},error: function (res) {console.log(res)}})}reader.readAsDataURL(file);}
3. 点击文件名时的事件
- 点击文件时,会下载对应的文件。 如果是图片类型,则直接显示在浏览器Dialog上
这里值得一提的是Image控件可以直接显示BASE64值的图片,不需要传入图片路径也可
onClickFilename: function (e) {var oData = e.getSource().getBindingContext().getProperty()var validFileTypes = ['gif', 'jpg', 'png', 'jpeg'];var vContent = oData.Attachmentif (validFileTypes.includes(oData.Filetype)) {// 创建图片控件this.oImage = new Image({src: oData.Attachment,width: "100%"});// 创建对话框this.oDialog = new Dialog({title: "Image Dialog",content: this.oImage,beginButton: new Button({text: "Close",press: function () {this.oDialog.close();}.bind(this)})});// 打开对话框this.oDialog.open();} else {var sContent = vContent.split(";")var Mimetype = sContent[0].split(":")var Docum = sContent[1].split(",")//下载需要把base64转为blobvar blob = this.base64toBlob(Docum[1], Mimetype[1]);File.save(blob, oData.Filename, oData.Filetype, Mimetype[1]);}},base64toBlob(base64Data, contentType) {contentType = contentType || '';var sliceSize = 512;var byteCharacters = atob(base64Data);var byteArrays = [];for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {var slice = byteCharacters.slice(offset, offset + sliceSize);var byteNumbers = new Array(slice.length);for (var i = 0; i < slice.length; i++) {byteNumbers[i] = slice.charCodeAt(i);}var byteArray = new Uint8Array(byteNumbers);byteArrays.push(byteArray);}var blob = new Blob(byteArrays, { type: contentType });return blob;}