如何使用 Uploadset 实现挂起的附件?

How to Implement Pending Attachments with Uploadset?

没有发布好的、完整的指南来帮助用户加快了解如何使用更新的 UploadSet 控件实现挂起的附件。

***欢迎改进。

这是带有附加功能的待上传的完整实现,例如:

  • 加载附件,
  • CheckBox 到 (de)select 所有文件以方便用户,
  • 下载,然后
  • 忙碌指示灯,而 Uploading/Downloading。

提示:避免使用另一个名为 UploadCollection 的控件,它有太多错误,并且在寻找替代方案时浪费了太多时间。 UploadSet 是你的 bug-free 闪亮,最好的朋友。

外观:*复选框的对齐和控件视觉效果的修改是通过自定义完成的 CSS(在此答案中引用)

Pre-requisites:

  • 脚手架 sap/m/MessageBoxMessageBoxsap/m/MessageToastMessageToast
  • UploadSet 的命名空间:xmlns:up="sap.m.upload"
  • 定义 var that = this 全局或在每个函数中使用 that
  1. 查看:

    <up:UploadSet id="attachmentUpl" instantUpload="false" maxFileSize="2" noDataDescription="" noDataText="" selectionChanged="onSelectionChangeAttachment"
    uploadCompleted="onUploadCompleted" uploadUrl="/sap/opu/odata/sap/Z9NRS_CONFIG_SRV/Z9NRS_REQ_ATTACHSet" visible="true">
        <up:toolbar>
            <OverflowToolbar>
                <CheckBox id="checkbox" select="onSelectAllAttachments" visible="false" />
                <ToolbarSpacer/>
                <Button id="upload" enabled="true" text="Upload" press="onStartUpload" type="Transparent" visible="true" />
                <Button id="remove" enabled="false" icon="sap-icon://delete" press="onRemove" type="Transparent" visible="true" />
                <Button id="download" enabled="false" icon="sap-icon://download" press="onDownload" type="Transparent" visible="true" />
            </OverflowToolbar>
        </up:toolbar>
    </up:UploadSet>
    
  2. 控制器:

onInit内:

var oAttachmentUpl= this.byId('attachmentUpl').getDefaultFileUploader();
oAttachmentUpl.setIcon("sap-icon://add").setIconOnly(true);
oAttachmentUpl.setMultiple(true); //lets user select more than 1file at a time in their FileExplorer

加载附件:

loadAttachments:function(){
      var sPath= "/Z9NRS_REQ_ATTACHSet?$filter=(ZNRS_REQUEST eq '"+sRequestId+"')";
      var oAttachmentUpl= this.byId("attachmentUpl");
      oAttachmentUpl.getList().setMode("MultiSelect");
      this.getView().getModel().read(sPath,{
        success:function(oData){
            var oAttachmentsModel= new JSONModel(oData);
            oAttachmentUpl.setModel(oAttachmentsModel).bindAggregation("items", "/results", new sap.m.upload.UploadSetItem({
                fileName: "{FILE_NAME}", mediaType: "{MIME_TYPE}", visibleEdit:false, visibleRemove:false,
                url: "/sap/opu/odata/sap/Z9NRS_CONFIG_SRV/Z9NRS_REQ_ATTACHSet(ZNRS_REQUEST='" + "{OBJECT_ID}" + "',FILE_NAME='" + "{FILE_NAME}" + "')/$value"
            }));
            if(oAttachmentUpl.getItems().length>0){
                that.byId('checkbox').setVisible(true);
            }
        },
        error:function(oError){that.parseErrorMsg()}
    });
}

其他一切:

onSelectAllAttachments: function(oEvent) {
    var aUploadedItems = this.byId("attachmentUpl").getItems(),
      bSelected = oEvent.getSource().getSelected();
    if (bSelected) { //if CheckBox is selected
      aUploadedItems.forEach(oItem => oItem.getListItem().setSelected(true));
      this.byId('download').setEnabled(true);
    } else {
      aUploadedItems.forEach(oItem => oItem.getListItem().setSelected(false));
      this.byId('remove').setEnabled(false);
      this.byId('download').setEnabled(false);
    }
  },
  onSelectionChangeAttachment: function() {
    if (this.byId("attachmentUpl").getList().getSelectedItems().length > 0) { //if user selects 1 or more uploaded item
      this.byId("remove").setEnabled(true);
      this.byId("download").setEnabled(true);
    } else {
      this.byId("remove").setEnabled(false);
      this.byId("download").setEnabled(false);
    }
  },
  onRemove: function(oEvent) {
    var oAttachmentUpl = this.byId("attachmentUpl");
    oAttachmentUpl.setBusy(true);
    oAttachmentUpl.getItems().forEach(oItem => {
      if (oItem.getListItem().getSelected()) {
        var sPath = oItem.getProperty("url").split("SRV")[1]; //eg /Z9NRS_REQ_ATTACHSet
        this.getView().getModel().remove(sPath, {
          success: function() {
            oAttachmentUpl.removeItem(oItem); //remove from displayed list
          },
          error: function(oError) {
            that.parseErrorMsg();
          }
        });
      }
    });
    oEvent.getSource().setEnabled(false);
    this.byId("download").setEnabled(false);

    if (oAttachmentUpl.getItems().length > 0) {
      this.byId('checkbox').setVisible(true);
    } else {
      this.byId('checkbox').setVisible(false);
    }
    oAttachmentUpl.setBusy(false);
  },
  onDownload: function(oEvent) {
    var oAttachmentUpl = this.byId("attachmentUpl");
    oAttachmentUpl.setBusy(true);
    oAttachmentUpl.getItems().forEach(oItem => {
      if (oItem.getListItem().getSelected()) {
        oItem.download(true);
        oItem.getListItem().setSelected(false);
      }
    });
    oAttachmentUpl.setBusy(false);
    oEvent.getSource().setEnabled(false);
  },
  onStartUpload: function() {
    var oAttachmentUpl = this.byId("attachmentUpl");
    var aIncompleteItems = oAttachmentUpl.getIncompleteItems();
    this.iIncompleteItems = aIncompleteItems.length; //used to turn off busy indicator upon completion of all pending uploads
    if (this.iIncompleteItems !== 0) {
      oAttachmentUpl.setBusy(true);
      this.i = 0; //used to turn off busy indicator when all uploads complete
      for (var i = 0; i < this.iIncompleteItems; i++) {
        var sFileName = aIncompleteItems[i].getProperty("fileName");
        var oXCSRFToken = new sap.ui.core.Item({
          key: "X-CSRF-Token",
          text: this.getOwnerComponent().getModel().getSecurityToken()
        });
        var oSlug = new sap.ui.core.Item({
          key: "SLUG",
          text: this.sRequestId + "/" + sFileName
        });
        oAttachmentUpl.addHeaderField(oXCSRFToken).addHeaderField(oSlug).uploadItem(aIncompleteItems[i]);
        oAttachmentUpl.removeAllHeaderFields(); //at least slug header field must be reset after each upload
      }
    }
  },
  onUploadCompleted: function() {
    this.i += 1;
    if (this.i === this.iIncompleteItems) { //turn off busy indicator when all attachments have completed uploading
      this.byId('attachmentUpl').setBusy(false);
    }
  },
  parseErrorMsg: function(oError) { //parses oData error messages dependent on different return values
    var oMessage, sType;
    if (oError.response) { //for update
      sType = typeof oError.response;
      if (sType === "string" || sType === "object") oMessage = JSON.parse(oError.response.body).error.message.value;
      else return MessageBox.error("Unhandled server error:\n\n" + oError.response + "\n\nReport this issue to Admin for a future fix.");
    } else if (oError.responseText) { //for create
      sType = typeof oError.responseText;
      if (sType === "string" || sType === "object") oMessage = JSON.parse(oError.responseText).error.message.value;
      else return MessageBox.error("Unhandled server error:\n\n" + oError.responseText + "\n\nReport this issue to Admin for a future fix.");
    } else if (!oError) return MessageToast.show("Error message is undefined");
    MessageBox.error(oMessage);
  }

  1. CSS:

/*uploadSet: align toolbar checkbox with ListItems' checkboxes*/
.sapMIBar.sapMTB.sapMTBNewFlex.sapMTBInactive.sapMTBStandard.sapMTB-Transparent-CTX {
    padding-left: 2px;
}
/*uploadSet: reduce height of each uploadItem*/
.sapMLIB.sapMLIB-CTX.sapMLIBShowSeparator.sapMLIBTypeInactive.sapMLIBFocusable.sapMCLI.sapMUCItem {
    padding-top: 10px;
    padding-bottom: 5px;
}
/*uploadSet: align uploadItem checkboxes to center*/
.sapMCb.sapMLIBSelectM {
    align-self: center !important;
}
/*uploadSet: remove rename icon from pending files*/
.sapMBtnBase.sapMBtn.sapMUCEditBtn.sapMUCFirstButton {
    display: none;
}
/*uploadSet: remove pending bar and text*/
.sapMFlexBox.sapMVBox.sapMFlexBoxJustifyStart.sapMFlexBoxAlignItemsStretch.sapMFlexBoxWrapNoWrap.sapMFlexBoxAlignContentStretch.sapMFlexBoxBGTransparent.sapMUSProgressBox {
    display: none;
}
/*uploadSet: center the x button for pending files*/
.sapMUCButtonContainer {
    align-self: center;
}

只需按下 Upload 按钮(位于 UploadSet 的工具栏中)即可上传所有待处理的附件。

所有项目都需要自定义才能使您的实施正常工作:

  • sPath 用于 loadAttachments 函数中的 oData 调用以及 UploadSetItem
  • 中的几乎所有参数
  • uploadUrl 属性 你的 UploadSet 控制
  • sPath 用于 onRemove 函数中的 oData 调用
  • SLUG header text onStartUpload 函数中的值

不包括的功能:

  • 上传完成后刷新UploadSet的项目列表

附加功能:

  • 不支持的文件类型,超过文件大小,Multi-File 进度(上传失败:

查看:将以下属性添加到您的 UploadSet,示例如下:

beforeUploadStarts="onBeforeUploadStarts" //this will update multi-file upload progress through MessageToast and MessageBox prompts
fileTypes="pdf,doc,docx,docm,ppt,pptx,xls,xlsx,jpg,jpeg,png"
fileTypeMismatch="onFileTypeMismatch"
maxFileSize="2"
fileSizeExceeded="onFileSizeExceeded"

控制器:

onBeforeUploadStarts: function(oEvent) { //track file upload progress
    var oUploadSet = oEvent.getSource(),
      iOldList = oUploadSet.getIncompleteItems().length;
    setTimeout(() => this.checkFileUploadFailed(oUploadSet, iOldList), 10000); // recursive func that checks status of itemslist
  },
checkFileUploadFailed: function(oUploadSet, iOldList) {
  if (iOldList !== 0) {
    var iNewList = oUploadSet.getIncompleteItems().length;
    if (iNewList === iOldList) {
      MessageToast.show("File upload(s) pending");
      if (!this.iPendingFilesCounter) this.iPendingFilesCounter = 0;
      this.iPendingFilesCounter += 1;
      if (this.iPendingFilesCounter === 3) {
        MessageBox.error("File uploads taking longer than expected.");
        oUploadSet.setBusy(false);
      }
      var iOldList = iNewList;
      setTimeout(() => this.checkFileUploadFailed(oUploadSet, iOldList), 10000);
    }
  }
},
  onFileTypeMismatch: function(oEvent) {
    var oItem = oEvent.getParameter("item");
    this.byId("attachmentUpl").removeIncompleteItem(oItem); //remove pending item user tried to add
    new sap.m.MessageToast.show(oItem.getProperty("fileName").split(".")[1] + " file type is not supported"); //show message toast with the specific fileType that isn't supported
  }
onFileSizeExceeded: function(oEvent) {
  var oAttachmentUpl = this.byId("attachmentUpl"),
    oItem = oEvent.getParameter("item");
  oAttachmentUpl.removeIncompleteItem(oItem); //remove pending item user tried to add
  new sap.m.MessageToast.show("Maximum file size of " + oAttachmentUpl.getMaxFileSize() + " MB exceeded"); //show message toast with the max file size supported
}