Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
SumitKundu
Active Participant
5,911
In the last blog post I discussed about how we can display images in a list report column in an app created using Fiori elements. In this blog, we shall discuss about how to upload image.

Before going through this blog post, it is recommended to read the previous one.

Sample source code for frontend app is here.

Scenario:


There will be a button in a column for each article record of the list and user will upload the image from local desktop/client system.

Yes, you guessed it right. The action column is added as an extension to the list report app. Please refer here for more details on how to add a column. We are using responsive table in this blog, but if your app uses a grid table, refer here.

Steps:



  1. Note: Please ensure the project type is smart template in project settings. This is automatically done when the project is created using 'List report' template wizard in SAP Web IDE.




Right click on the project -> New -> Extension

Choose 'List Report Extension' in 'Template Selection' tab and choose 'Next':

Choose Entity set from drop down and provide a name for the fragment to be generated.

Choose 'Next'.

Choose Finish.

This will create a folder 'ext' and a fragment upload.fragment.xml within.

Create another file in the folder 'ext' : uploadCell.fragment.xml. Refer SAP documentation to understand what is happening.

So two fragments will be created :

 a. sos.uploadimage.ext.view.upload.fragment.xml,

 b. sos.uploadimage.ext.view.uploadCell.fragment.xml

Alos after the list report app is extended, manifest.json file should look like below.

Below are the sample code.

manifest.json 
"sap.ui5": {

...

"extends": {
"extensions": {
"sap.ui.viewExtensions": {
"sap.suite.ui.generic.template.ListReport.view.ListReport": {
"ResponsiveTableColumnsExtension|ZCDS_C_SKUIMAGE": {
"type": "XML",
"className": "sap.ui.core.Fragment",
"fragmentName": "sos.uploadimage.ext.view.upload"
},
"ResponsiveTableCellsExtension|ZCDS_C_SKUIMAGE": {
"type": "XML",
"className": "sap.ui.core.Fragment",
"fragmentName": "sos.uploadimage.ext.view.uploadCell"
}
}
},
"sap.ui.controllerExtensions": {
"sap.suite.ui.generic.template.ListReport.view.ListReport": {
"controllerName": "sos.uploadimage.ext.controller.ListReportExt",
"sap.ui.generic.app": {
"ZCDS_C_SKUIMAGE": {
"EntitySet": "ZCDS_C_SKUIMAGE"
}
}
}
}
}
},

...
}

 

sos.uploadimage.ext.view.upload.frgament.xml
<core:FragmentDefinition xmlns:core="sap.ui.core" xmlns="sap.m">
<Column id="ExtensionWizard::ColumnBreakout">
<Text text="{i18next>action}"/>
<customData>
<core:CustomData key="p13nData" value='\{"columnKey": "Test", "columnIndex" : "101"}'/>
</customData>
</Column>
</core:FragmentDefinition>

sos.uploadimage.ext.view.uploadCell.frgament.xml
<core:FragmentDefinition xmlns:core="sap.ui.core" xmlns="sap.m" xmlns:u="sap.ui.unified">
<VBox>
<u:FileUploader id="fileUploader" name="myFileUpload" tooltip="Upload your file to the local server" uploadComplete="handleUploadComplete"
uploadAborted="handleUploadAbort" buttonOnly="true" buttonText="Upload Image" sendXHR="true" uploadOnChange="true" useMultipart="false"
sameFilenameAllowed="true" change="handleValueChange" style="Emphasized" placeholder="Choose a file for Upload...">
<u:headerParameters>
<u:FileUploaderParameter name="slug" value="{CatalogSKU}"/>
</u:headerParameters>
</u:FileUploader>
</VBox>
</core:FragmentDefinition>

 

Note: In the sample code, we have used property sendXHR="true" above.This property is not supported by Internet Explorer 9.  Please adjust code accordingly.


2. We also need to add code to handle the events raised by the control sap.ui.unified.FileUploader introduced in fragment uploadCell.frgament.xml.

A quick way to add extension controller is again to extend using wizard as shown in step 1 but this time choosing 'Action' radio button in 'Extension Settings' tab of the wizard.

Delete the 'Action' part from manifest.json as we are not really using action button feature. [See the source code from github]

Extension wizard will also add another folder 'controller' and file 'ListReportExt.controller.js' within.

Overwrite the code in this file with the content below. [See the source code from github]

ListReportExt.controller.js
sap.ui.controller("sos.uploadimage.ext.controller.ListReportExt", {
onInit: function () {
var oSmartTable = this.byId("listReport");
oSmartTable.setEnableAutoBinding(true);
var i18nModel = new sap.ui.model.resource.ResourceModel({
bundleName: "sos.uploadimage.i18n.i18n"
});
this.getView().setModel(i18nModel, "i18next");
this.oBundle = this.getView().getModel("i18next").getResourceBundle();
},
handleValueChange: function (oEvent) {
this.getView().setBusy(true);
var oSource = oEvent.getSource();
if (oSource.getBindingContext().getProperty("CatalogSKU")) {
oSource.setUploadUrl(oSource.getModel().sServiceUrl +
oSource.getModel().createKey("/ZCDS_C_SKUIMAGE", {
CatalogSKU: oSource.getBindingContext().getProperty("CatalogSKU")
}) + "/to_SOSImage");

}
oSource.getModel().refreshSecurityToken();
oSource.addHeaderParameter(
new sap.ui.unified.FileUploaderParameter({
name: "x-csrf-token",
value: oSource.getModel().getHeaders()["x-csrf-token"]
}));
},
handleUploadComplete: function (oEvent) {
var sResponse = oEvent.getParameter("response");
this.getView().setBusy(false);
if (sResponse) {
var sMsg = "";
var sStatus = oEvent.getParameter("status");
if (sStatus.toString() === "201" || sStatus.toString() === "202") {
sMsg = this.oBundle.getText("uploadSuccess", [oEvent.getParameter("fileName")]);
oEvent.getSource().setValue("");
this.getView().byId("listReport").rebindTable();
} else {
sMsg = this.oBundle.getText("uploadError", [oEvent.getParameter("fileName")]);
oEvent.getSource().setValue("");
}
sap.m.MessageToast.show(sMsg);
}
},
handleUploadAbort: function (oEvent) {
this.getView().setBusy(false);
sap.m.MessageToast.show(this.oBundle.getText("uploadAborted"));
},

handleFileSize:function (oEvent) {
//this.getView().getModel(["i18next]").

var allMessage = this.getView().getModel("i18next").getResourceBundle().getText("fileSize",[oEvent.getParameter("fileName")]);
sap.m.MessageBox.show(allMessage, {
icon: sap.m.MessageBox.Icon.ERROR, // default sap-icon://message-success
title: this.getView().getModel("i18next").getResourceBundle().getText("sizeError"), // default
actions: sap.m.MessageBox.Action.OK, // default
onClose: null, // default
styleClass: "", // default
initialFocus: null, // default
textDirection: sap.ui.core.TextDirection.Inherit // default
});
},

handleTypeMismatch: function(oEvent) {

var allMessage = this.getView().getModel("i18next").getResourceBundle().getText("fileType",[oEvent.getParameter("fileName")]);
sap.m.MessageBox.show(allMessage, {
icon: sap.m.MessageBox.Icon.ERROR, // default sap-icon://message-success
title: this.getView().getModel("i18next").getResourceBundle().getText("typeError"), // default
actions: sap.m.MessageBox.Action.OK, // default
onClose: null, // default
styleClass: "", // default
initialFocus: null, // default
textDirection: sap.ui.core.TextDirection.Inherit // default
});


}
});

 

3. Function handleValueChange: This hander is triggered when a file is uploaded from local device. We are setting the uploadURl property of FIleUploader control appropriately to the navigation property to_SOSImage which is actually the media entity type.

4. Functions handleUploadComplete and handleUploadAbort issues appropriate messages if upload succeeds or fails respectively.

5. Now that frontend coding is done, in S/4HANA or backend system, add below code in method /iwbep/if_mgw_appl_srv_runtime~create_stream of DPC_EXT class.
METHOD /iwbep/if_mgw_appl_srv_runtime~create_stream.

* Local data declaration
DATA :
lv_matnr TYPE matnr,
lt_tab TYPE solix_tab,
lv_buffer TYPE xstring,
lv_imagekey TYPE char10,
lv_filesize TYPE i,
lv_url TYPE DIRNAME,
ls_entity TYPE zcl_z_images_mpc=>ts_zcds_i_imagetype.

FIELD-SYMBOLS : <lfs_cat_sku> TYPE zfiap_cat_sku.

IF iv_entity_name = 'ZCDS_I_IMAGEType'. " Check the Image entity
READ TABLE it_key_tab INTO DATA(ls_key_tab) WITH KEY name = 'CatalogSKU'.
IF sy-subrc = 0.

CALL FUNCTION 'CONVERSION_EXIT_MATN1_INPUT'
EXPORTING
input = ls_key_tab-value
IMPORTING
output = lv_matnr
EXCEPTIONS
length_error = 1
OTHERS = 2.
IF sy-subrc = 0.

ENDIF.

* Select Catalog details for the article
SELECT SINGLE * FROM zfiap_cat_sku
INTO @DATA(ls_cat_sku)
WHERE matnr = @lv_matnr.
IF sy-subrc = 0.
ASSIGN ls_cat_sku TO <lfs_cat_sku>.

ls_entity-catalogsku = <lfs_cat_sku>-matnr = lv_matnr.
ls_entity-catalogitmkey = <lfs_cat_sku>-ctlg_itm_key.
ls_entity-mime_type = <lfs_cat_sku>-mime_type = is_media_resource-mime_type.

SHIFT lv_matnr LEFT DELETING LEADING '0'.
* Pass the image name
<lfs_cat_sku>-image_name = ls_entity-image_name = iv_slug.

******************* IMPORTANT READING ******************************************************
**Generate a unique key for the image_key field here and assihm to <lfs_cat_sku>-image_key
**Below code saves the file in application directory, but adjust the code according
**to your own content repositiry needs
********************************************************************************************


* Convert rawstring to binary format
CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
EXPORTING
buffer = is_media_resource-value
IMPORTING
output_length = lv_filesize
TABLES
binary_tab = lt_tab[].

lv_imagekey = <lfs_cat_sku>-image_key.

* Get AL11 directory path
CALL FUNCTION 'ZDIR_INTERFACE_PATH_GET'
EXPORTING
im_dirname = 'DIR_INTERFACE'
IMPORTING
ex_path = lv_url.

* Prepare image URL of AL11 to save in catalog SKU table
CONCATENATE lv_url
'/SKU_IMAGES/'(001)
lv_matnr
'_'(002)
lv_imagekey
INTO <lfs_cat_sku>-image_url.
ls_entity-imageurl = <lfs_cat_sku>-image_url.

<lfs_cat_sku>-file_size = lv_filesize.
IF lt_tab[] IS NOT INITIAL.
* Upload the image to AL11
OPEN DATASET <lfs_cat_sku>-image_url FOR OUTPUT IN BINARY MODE.
IF sy-subrc = 0.
LOOP AT lt_tab INTO DATA(ls_tab).
TRANSFER ls_tab TO <lfs_cat_sku>-image_url.
ENDLOOP.
CLOSE DATASET <lfs_cat_sku>-image_url.

CALL FUNCTION 'ENQUEUE_EZFIAP_CAT_SKU'
EXPORTING
mode_zfiap_cat_sku = 'E'
mandt = sy-mandt
matnr = <lfs_cat_sku>-matnr
_scope = '2'
EXCEPTIONS
foreign_lock = 1
system_failure = 2
OTHERS = 3.
IF sy-subrc = 0.
* Modify the catalog AKU table with image URL
MODIFY zfiap_cat_sku FROM <lfs_cat_sku>.
ENDIF.

CALL FUNCTION 'DEQUEUE_EZFIAP_CAT_SKU'
EXPORTING
mode_zfiap_cat_sku = 'E'
mandt = sy-mandt
matnr = <lfs_cat_sku>-matnr
_scope = '3'.

ENDIF.
ENDIF.
ENDIF.
ENDIF.

* Copy entity data to entity reference
copy_data_to_ref( EXPORTING is_data = ls_entity
CHANGING cr_data = er_entity ).

ENDIF.

ENDMETHOD.

As mentioned in the previous blog, for simplicity, we are storing the image file in application server directory, but adapt the code according to your own content repository.

6. Test the app by uploading an image from local device.



 

Conclusion


In this blog series, we saw how to display and upload image for each record in a list report created with Fiori Elements List Report Floorplan.
5 Comments
Labels in this area