Save attachment to GOS from SAPUI5 Fiori

Here is a simple walkthrough on uploading a file through SAPUI5 interface and saving it as a GOS attachment in SAP system. This example uses purchase order business object (BUS2012). If you plan to use another type of document, you should find corresponding business object and change it accordingly.

Create a structure to transfer media info between backend and frontend.

Create function modules to upload, download and list attachments.

FUNCTION z_upload_attachment.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     VALUE(IV_OBJECT_ID) TYPE  SIBFBORIID
*"     VALUE(IV_FILENAME) TYPE  SO_OBJ_DES
*"     VALUE(IV_VALUE) TYPE  XSTRING
*"  EXPORTING
*"     VALUE(ES_ATTACHMENT) TYPE  ZST_ATTACHMENT
*"     VALUE(ES_RETURN) TYPE  BAPIRET2
*"----------------------------------------------------------------------

  DATA ls_folder_id TYPE soodk.
  CALL FUNCTION 'SO_FOLDER_ROOT_ID_GET'
    EXPORTING
      region                = 'B'
    IMPORTING
      folder_id             = ls_folder_id
    EXCEPTIONS
      communication_failure = 1
      owner_not_exist       = 2
      system_failure        = 3
      x_error               = 4
      OTHERS                = 5.

  DATA lv_extension TYPE sood-file_ext.
  CALL FUNCTION 'TRINT_FILE_GET_EXTENSION'
    EXPORTING
      filename  = iv_filename
    IMPORTING
      extension = lv_extension.

  DATA: lv_output_length TYPE i,
        lt_solix         TYPE solix_tab.
  CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
    EXPORTING
      buffer        = iv_value
    IMPORTING
      output_length = lv_output_length
    TABLES
      binary_tab    = lt_solix.

  DATA lt_soli  TYPE soli_tab.
  CALL FUNCTION 'SO_SOLIXTAB_TO_SOLITAB'
    EXPORTING
      ip_solixtab = lt_solix
    IMPORTING
      ep_solitab  = lt_soli.

  DATA: ls_object_hd_change TYPE sood1,
        lt_objhead          TYPE STANDARD TABLE OF soli.

  ls_object_hd_change-objla = sy-langu.
  ls_object_hd_change-objnam = 'MESSAGE'.
  ls_object_hd_change-objdes = iv_filename.
  ls_object_hd_change-file_ext = lv_extension.
  ls_object_hd_change-objlen = lv_output_length.

  DATA lv_mimetype TYPE mimetypes-type.
  CALL FUNCTION 'SDOK_MIMETYPE_GET'
    EXPORTING
      extension = lv_extension
    IMPORTING
      mimetype  = lv_mimetype.

  lt_objhead = VALUE #( ( line = '&SO_FILENAME=' && iv_filename )
                        ( line = '&SO_FORMAT=BIN' )
                        ( line = '&SO_CONTTYPE=' && lv_mimetype ) ).

  DATA ls_object_id TYPE soodk.
  CALL FUNCTION 'SO_OBJECT_INSERT'
    EXPORTING
      folder_id                  = ls_folder_id
      object_hd_change           = ls_object_hd_change
      object_type                = 'EXT'
    IMPORTING
      object_id                  = ls_object_id
    TABLES
      objcont                    = lt_soli
      objhead                    = lt_objhead
    EXCEPTIONS
      active_user_not_exist      = 1
      communication_failure      = 2
      component_not_available    = 3
      dl_name_exist              = 4
      folder_not_exist           = 5
      folder_no_authorization    = 6
      object_type_not_exist      = 7
      operation_no_authorization = 8
      owner_not_exist            = 9
      parameter_error            = 10
      substitute_not_active      = 11
      substitute_not_defined     = 12
      system_failure             = 13
      x_error                    = 14
      OTHERS                     = 15.
  IF sy-subrc <> 0.
    es_return-type   = 'E'.
    es_return-id     = sy-msgid.
    es_return-number = sy-msgno.
    es_return-message_v1 = sy-msgv1.
    es_return-message_v2 = sy-msgv2.
    es_return-message_v3 = sy-msgv3.
    es_return-message_v4 = sy-msgv4.
    IF es_return-id IS INITIAL.
      es_return-id     = 'SV'.
      es_return-number = '171'.
    ENDIF.
    RETURN.
  ENDIF.

  es_attachment-object_type = 'BUS2012'.
  es_attachment-object_cat  = 'BO'.
  es_attachment-document_id = ls_folder_id-objtp && ls_folder_id-objyr && ls_folder_id-objno &&
                              ls_object_id-objtp && ls_object_id-objyr && ls_object_id-objno.
  es_attachment-file_name   = iv_filename.
  es_attachment-mime_type   = lv_mimetype.


  DATA: ls_object_a TYPE sibflporb,
        ls_object_b TYPE sibflporb.

  ls_object_a-instid = iv_object_id.
  ls_object_a-typeid = 'BUS2012'.
  ls_object_a-catid  = 'BO'.
  ls_object_b-instid  = es_attachment-document_id.
  ls_object_b-typeid = 'MESSAGE'.
  ls_object_b-catid  = 'BO'.

  TRY.
      cl_binary_relation=>create_link(
        EXPORTING
          is_object_a = ls_object_a
          is_object_b = ls_object_b
          ip_reltype  = 'ATTA' ).
    CATCH cx_obl_parameter_error.
    CATCH cx_obl_model_error.
    CATCH cx_obl_internal_error.
  ENDTRY.

ENDFUNCTION.
FUNCTION z_download_attachment.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     VALUE(IV_DOCUMENT_ID) TYPE  DOCUMENTID
*"  EXPORTING
*"     VALUE(EV_VALUE) TYPE  XSTRING
*"     VALUE(EV_MIME_TYPE) TYPE  STRING
*"     VALUE(EV_FILENAME) TYPE  SO_OBJ_DES
*"----------------------------------------------------------------------

  DATA: ls_document_data TYPE sofolenti1,
        lt_content       TYPE STANDARD TABLE OF solix.

  CALL FUNCTION 'SO_DOCUMENT_READ_API1'
    EXPORTING
      document_id                = CONV sofolenti1-doc_id( iv_document_id )
    IMPORTING
      document_data              = ls_document_data
    TABLES
      contents_hex               = lt_content
    EXCEPTIONS
      document_id_not_exist      = 1
      operation_no_authorization = 2
      x_error                    = 3
      OTHERS                     = 4.

  CALL FUNCTION 'SCMS_BINARY_TO_XSTRING'
    EXPORTING
      input_length = CONV i( ls_document_data-doc_size )
    IMPORTING
      buffer       = ev_value
    TABLES
      binary_tab   = lt_content
    EXCEPTIONS
      failed       = 1
      OTHERS       = 2.

  DATA lv_mimetype TYPE mimetypes-type.
  CALL FUNCTION 'SDOK_MIMETYPE_GET'
    EXPORTING
      extension = ls_document_data-obj_type
    IMPORTING
      mimetype  = lv_mimetype.
  ev_mime_type = lv_mimetype.
  ev_filename = ls_document_data-obj_descr.

ENDFUNCTION.
FUNCTION z_get_attachments.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     VALUE(IV_OBJECT_ID) TYPE  SIBFBORIID
*"  EXPORTING
*"     VALUE(ET_ATTACHMENT) TYPE  ZTT_ATTACHMENT
*"----------------------------------------------------------------------

  TRY.
      cl_binary_relation=>read_links_of_objects(
        EXPORTING
          it_objects = VALUE #( ( instid = iv_object_id typeid = 'BUS2012' catid = 'BO' ) )
        IMPORTING
          et_links_a = DATA(lt_links) ).
    CATCH cx_obl_model_error.
    CATCH cx_obl_parameter_error.
    CATCH cx_obl_internal_error.
  ENDTRY.

  LOOP AT lt_links ASSIGNING FIELD-SYMBOL(<ls_link>).
    SELECT SINGLE * FROM sood
      WHERE objtp = @<ls_link>-instid_b+17(3)
        AND objyr = @<ls_link>-instid_b+20(2)
        AND objno = @<ls_link>-instid_b+22
      INTO @DATA(ls_sood).
    IF sy-subrc = 0.
      APPEND INITIAL LINE TO et_attachment ASSIGNING FIELD-SYMBOL(<ls_attach>).
      <ls_attach>-object_id    = <ls_link>-instid_a.
      <ls_attach>-object_type  = <ls_link>-typeid_a.
      <ls_attach>-object_cat   = <ls_link>-catid_a.
      <ls_attach>-document_id  = <ls_link>-instid_b.
      <ls_attach>-file_name    = ls_sood-objdes.
      <ls_attach>-creator      = ls_sood-crono.
      <ls_attach>-creator_name = ls_sood-cronam.
      <ls_attach>-created_on   = <ls_link>-utctime.
      DATA lv_mimetype TYPE mimetypes-type.
      CALL FUNCTION 'SDOK_MIMETYPE_GET'
        EXPORTING
          extension = ls_sood-file_ext
        IMPORTING
          mimetype  = lv_mimetype.
      <ls_attach>-mime_type    = lv_mimetype.
      CLEAR lv_mimetype.
    ENDIF.
  ENDLOOP.

ENDFUNCTION.

Create related entity type and mark it as media.

Redefine the “DEFINE” method of MPC_EXT class.

METHOD define.
  super->define( ).
  model->get_entity_type( iv_entity_name = `Attachment` )->get_property( iv_property_name = `MimeType` )->set_as_content_type( ).
ENDMETHOD.

Redefine the “/IWBEP/IF_MGW_APPL_SRV_RUNTIME~CREATE_STREAM” method of DPC_EXT class.

METHOD /iwbep/if_mgw_appl_srv_runtime~create_stream.

  DATA(lv_entity_set_name) = io_tech_request_context->get_entity_set_name( ).

  CASE lv_entity_set_name.
    WHEN 'AttachmentSet'.

      DATA: lv_object_id  TYPE sibfboriid,
            lv_filename   TYPE so_obj_des,
            lv_file_id    TYPE soodk,
            ls_attachment TYPE zst_attachment,
            ls_return     TYPE bapiret2.

      SPLIT iv_slug AT ';' INTO lv_filename lv_object_id.

      CALL FUNCTION 'Z_UPLOAD_ATTACHMENT'
        EXPORTING
          iv_object_id  = lv_object_id
          iv_filename   = lv_filename
          iv_value      = is_media_resource-value
        IMPORTING
          es_attachment = ls_attachment
          es_return     = ls_return.

      IF ls_return-type = 'E'.
        DATA(lo_exception) = NEW /iwbep/cx_mgw_busi_exception( ).
        lo_exception->get_msg_container( )->add_message_from_bapi( is_bapi_message = ls_return iv_message_target = CONV string( ls_return-field ) ).
        RAISE EXCEPTION lo_exception.
      ENDIF.

      copy_data_to_ref( EXPORTING is_data = ls_attachment CHANGING cr_data = er_entity ).

  ENDCASE.

ENDMETHOD.

Redefine the “/IWBEP/IF_MGW_APPL_SRV_RUNTIME~GET_STREAM” method of DPC_EXT class.

  METHOD /iwbep/if_mgw_appl_srv_runtime~get_stream.

    DATA ls_stream  TYPE ty_s_media_resource.
    DATA(lv_entity_set_name) = io_tech_request_context->get_entity_set_name( ).
    DATA(lt_keys) = io_tech_request_context->get_keys( ).

    CASE lv_entity_set_name.
      WHEN 'AttachmentSet'.
        DATA: lv_document_id TYPE documentid,
              lv_filename    TYPE so_obj_des.
        lv_document_id = lt_keys[ name = 'DOCUMENT_ID' ]-value.
        CALL FUNCTION 'Z_DOWNLOAD_ATTACHMENT'
          EXPORTING
            iv_document_id = lv_document_id
          IMPORTING
            ev_value       = ls_stream-value
            ev_mime_type   = ls_stream-mime_type
            ev_filename    = lv_filename.

        DATA ls_lheader TYPE ihttpnvp.
        lv_filename = escape( val = lv_filename format = cl_abap_format=>e_url ).
        ls_lheader-name = 'Content-Disposition'.
        ls_lheader-value = 'outline; filename=”' && lv_filename && '”;'.
        set_header( is_header = ls_lheader ).

        copy_data_to_ref( EXPORTING is_data = ls_stream
                          CHANGING  cr_data = er_stream ).

    ENDCASE.

  ENDMETHOD.

Add UploadSet control to your view.

<mvc:View xmlns:html="http://www.w3.org/1999/xhtml" xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m" xmlns:f="sap.ui.layout.form"
	xmlns:core="sap.ui.core" controllerName="co.arteis.sospo.controller.Create" displayBlock="true">
	<App>
		<pages>
			<Page id="page" title="{i18n>title}" showFooter="true" floatingFooter="true" busy="createView&gt;/page/busy" enableScrolling="true"
				showNavButton="true" navButtonPress=".onNavButtonPress">
				<content>
					<upload:UploadSet id="UploadSet" instantUpload="false" showIcons="true" visible="{worklistView>/page/editable}" terminationEnabled="true"
						maxFileNameLength="55" beforeUploadStarts="onBeforeUploadStarts" uploadCompleted="onUploadCompleted" class="sapUiResponsiveMargin"/>
				</content>
				<footer>
					<OverflowToolbar>
						<ToolbarSpacer/>
						<Button text="{i18n>PlaceOrder}" type="Emphasized" press=".onOrderPress" visible="{createView>/page/editable}"/>
					</OverflowToolbar>
				</footer>
			</Page>
		</pages>
	</App>
</mvc:View>

Set upload url in onInit function of controller.

		onInit: function() {
			var oViewModel = new JSONModel({
				page: {
					busy: false,
					editable: true
				},
				data: {
					items: [{}],
					attachments: []
				}
			});
			this.setModel(oViewModel, "createView");

			this.byId("UploadSet").setUploadUrl(this.getOwnerComponent().getModel().sServiceUrl + "/AttachmentSet");
		},

Add event handler functions of UploadSet to controller.

		startUpload: function() {
			var oUploadSet = this.byId("UploadSet");
			var cFiles = oUploadSet.getIncompleteItems().length;

			if (cFiles > 0) {
				oUploadSet.upload();
			}
		},

		onBeforeUploadStarts: function(oEvent) {
			var oUploadSet = oEvent.getSource();
			var oItemToUpload = oEvent.getParameter("item");
			var oCustomerHeaderToken = new sap.ui.core.Item({
				key: "x-csrf-token",
				text: this.getModel().getSecurityToken()
			});

			// Header Slug
			var oCustomerHeaderSlug = new sap.ui.core.Item({
				key: "slug",
				text: oItemToUpload.getFileName() + ";" + this._documentNumber
			});

			oUploadSet.removeAllHeaderFields();
			oUploadSet.addHeaderField(oCustomerHeaderToken);
			oUploadSet.addHeaderField(oCustomerHeaderSlug);
		},

		onUploadCompleted: function(oEvent) {
			this.getModel("worklistView").refresh(true);
		},

Finally, call startUpload function after your document is created.

		onOrderPress: function(oEvent) {
			var oViewModel = this.getModel("createView");
			oViewModel.setProperty("/page/busy", true);
			var aItPoItemSet = oViewModel.getProperty("/data/items").map(function(oItem) {
				return {
					Matnr: oItem.Matnr,
					Menge: this.convertToFloat(oItem.Menge, 2),
					Brtwr: this.convertToFloat(oItem.Brtwr, 2),
					TaxPercent: oItem.TaxPercent
				};
			}.bind(this));
			var oDocument = {
				Application: "SOSPO",
				Aedat: oViewModel.getProperty("/data/Aedat"),
				Ihrez: oViewModel.getProperty("/data/Ihrez"),
				ItPoItemSet: aItPoItemSet
			};
			this.getView().getModel().create("/IsPoHeadSet", oDocument, {
				success: function(oData, oResponse) {
					oViewModel.setProperty("/page/editable", false);
					this._documentNumber = oData.Ebeln;
					this.startUpload();
					oViewModel.setProperty("/page/busy", false);
					sap.m.MessageToast.show(this.getResourceBundle().getText("savedMessage"));
				}.bind(this),
				error: function(oError) {
					oViewModel.setProperty("/page/busy", false);
				}.bind(this)
			});

		},

Leave a Reply