This is a test message to test the length of the message box.
Login
|
ABAP RAP Upload of Files
Created by Software-Heroes

RAP - File Upload (Stream)

10398

How can you easily load files into your RAP object and make them available in ABAP? Let's take a look at the details.

Advertising


In this article we will look at one way of uploading files, and we will discuss the different ways of using it.

 

Introduction

Uploading and downloading files is now standard in applications. Therefore, in the ABAP RESTful Programming Model we also need a simple solution to do this. Today we will look at uploading, i.e. storing a file in our application. To do this, we will extend the Report Pattern application with the additional function.

 

Extension

In this section, we will extend the application with two uploads to load an Excel file and an image into the application.

 

Table

In the first step, we need to extend the table. To upload files, we need three fields with a certain length.

attachment    : abap.rawstring(0);
mimetype      : abap.char(128);
filename      : abap.char(128);

 

The attachment is the file in binary form, the mimetype describes the type of the file and the filename is the name of the file after uploading. The length of the individual fields is fixed. In the first step we extend the table ZBS_DRP_ADDCURR by the 6 fields.

define table zbs_drp_addcurr {
  key client         : abap.clnt not null;
  key currency       : waers not null;
  ccomment           : abap.char(60);
  documentation      : abap.string(0);
  picture_url        : abap.string(0);
  last_editor        : abap.char(12);
  excel_attachment   : abap.rawstring(0);
  excel_mimetype     : abap.char(128);
  excel_filename     : abap.char(128);
  picture_attachment : abap.rawstring(0);
  picture_mimetype   : abap.char(128);
  picture_filename   : abap.char(128);
  local_last_changed : abp_locinst_lastchange_tstmpl;
  last_changed       : abp_lastchange_tstmpl;
}

 

In the second step, we extend our draft table ZBS_DRP_CURRD so that our application continues to work. We remove the underscores because we are still normalizing the fields in the Core Data Service.

define table zbs_drp_currd {
  key client             : abap.clnt not null;
  key currency           : waers not null;
  decimals               : abap.int1;
  currencyisocode        : abap.char(3);
  alternativecurrencykey : abap.char(3);
  currencyname           : abap.char(40);
  currencyshortname      : abap.char(15);
  currencycomment        : abap.char(60);
  documentation          : abap.string(0);
  pictureurl             : abap.string(0);
  lasteditor             : abap.char(12);
  excelattachment        : abap.rawstring(0);
  excelmimetype          : abap.char(128);
  excelfilename          : abap.char(128);
  pictureattachment      : abap.rawstring(0);
  picturemimetype        : abap.char(128);
  picturefilename        : abap.char(128);
  locallastchanged       : abp_locinst_lastchange_tstmpl;
  lastchanged            : abp_lastchange_tstmpl;
  "%admin"               : include sych_bdl_draft_admin_inc;
}

 

Basis

Since we use a basic view "ZBS_B_DRPAdditionalCurrency" to normalize the fields in the data model, we also add the fields here and rename them. This means that they also match the field names in the draft table.

define view entity ZBS_B_DRPAdditionalCurrency
  as select from zbs_drp_addcurr
{
  key currency           as Currency,
      ccomment           as CurrencyComment,
      documentation      as Documentation,
      picture_url        as PictureURL,
      last_editor        as LastEditor,
      excel_attachment   as ExcelAttachement,
      excel_mimetype     as ExcelMimetype,
      excel_filename     as ExcelFilename,
      picture_attachment as PictureAttachement,
      picture_mimetype   as PictureMimetype,
      picture_filename   as PictureFilename,
      last_changed       as LastChanged,
      local_last_changed as LocalLastChanged
}

 

Interface

In the root view of the object, we also add the fields accordingly so that they are then available in the RAP object.

define root view entity ZBS_R_DRPCurrency
  as select from I_Currency
  composition of many ZBS_I_DRPCurrencyCountry          as _Country
  association of one to one ZBS_B_DRPAdditionalCurrency as _Data on _Data.Currency = $projection.Currency
  association of one to one I_BusinessUserVH            as _User on _User.UserID = $projection.lasteditor
{
  key Currency,
      Decimals,
      CurrencyISOCode,
      AlternativeCurrencyKey,
      _Text[ Language = $session.system_language ].CurrencyName,
      _Text[ Language = $session.system_language ].CurrencyShortName,
      _Data.CurrencyComment,
      _Data.Documentation,
      _Data.PictureURL,
      _Data.LastEditor,
      _Data.ExcelAttachement,
      _Data.ExcelMimetype,
      _Data.ExcelFilename,
      _Data.PictureAttachement,
      _Data.PictureMimetype,
      _Data.PictureFilename,
      _Data.LastChanged,
      _Data.LocalLastChanged,
      _Country,
      _User
}

 

Consumption

To complete the extension of the data model, we add the fields in the Consumption View.

define root view entity ZBS_C_DRPCurrency
  provider contract transactional_query
  as projection on ZBS_R_DRPCurrency
{
      @Search.defaultSearchElement: true
      @Search.fuzzinessThreshold: 1.0
      @Search.ranking: #HIGH
  key Currency,
      Decimals,
      CurrencyISOCode,
      AlternativeCurrencyKey,
      @Search.defaultSearchElement: true
      @Search.fuzzinessThreshold: 0.7
      @Search.ranking: #MEDIUM
      CurrencyName,
      @Search.defaultSearchElement: true
      @Search.fuzzinessThreshold: 0.8
      @Search.ranking: #MEDIUM
      CurrencyShortName,
      CurrencyComment,
      Documentation,
      PictureURL,
      ExcelAttachement,
      ExcelMimetype,
      ExcelFilename,
      PictureAttachement,
      PictureMimetype,
      PictureFilename,
      LastEditor,
      _User.PersonFullName as EditorName,
      _Country : redirected to composition child ZBS_C_DRPCurrencyCountry
}

 

Metadata Extension

In the Metadata Extension we also adopt the fields so that they are displayed in the UI. To do this we also create a new section in the "UI.Facet" on the object page.

{
  id         : 'idFiles',
  label      : 'Files',
  position   : 35,
  type       : #IDENTIFICATION_REFERENCE,
  targetQualifier: 'FILE'
}

 

In the lower part we add the fields. You can hide the Mimetype and the file name and only show the Attachment field.

@UI:{
  identification: [{ position: 80, qualifier: 'FILE' }]
}
@EndUserText.label: 'Excel'
ExcelAttachement;

@UI.hidden: true
ExcelMimetype;

@UI.hidden: true
ExcelFilename;

@UI:{
  identification: [{ position: 80, qualifier: 'FILE' }]
}
@EndUserText.label: 'Picture'
PictureAttachement;

@UI.hidden: true
PictureMimetype;

@UI.hidden: true
PictureFilename;

 

Behavior

In the behavior definition we add the mapping so that the data ends up in the database when it is saved.

mapping for zbs_drp_addcurr
  {
    Currency           = currency;
    CurrencyComment    = ccomment;
    Documentation      = documentation;
    PictureURL         = picture_url;
    LastEditor         = last_editor;
    ExcelAttachement   = excel_attachment;
    ExcelMimetype      = excel_mimetype;
    ExcelFilename      = excel_filename;
    PictureAttachement = picture_attachment;
    PictureMimetype    = picture_mimetype;
    PictureFilename    = picture_filename;
    LocalLastChanged   = local_last_changed;
    LastChanged        = last_changed;
  }

 

Result

If we now look at the current result in the UI, the fields are now there, but still look very much like standard input. At least the fields are already there and our extension is complete.

 

Upload Dialog

In this section we now want to add the upload dialog to the fields. To do this we only need to add a few annotations to prepare the fields.

 

Mimetype

We first need to set the Mimetype field with the new annotation from the "Semantics" area. This tells Fiori that there is a Mimetype in the field.

@Semantics.mimeType: true
ExcelMimetype,

 

Attachment

In the next step, we expand the attachment field with the necessary information and pass the fields for the mimetype and the filename. The information is needed for display and upload later.

@Semantics.largeObject: {
  mimeType : 'ExcelMimetype',
  fileName : 'ExcelFilename',
  contentDispositionPreference: #INLINE
}
ExcelAttachement,

 

Result

The finished annotation looks like this. Since this is more of a technical annotation, we have transferred it to the Consumption View and not to the Metadata Extension.

@Semantics.largeObject: {
  mimeType : 'ExcelMimetype',
  fileName : 'ExcelFilename',
  contentDispositionPreference: #INLINE
}
ExcelAttachement,
@Semantics.mimeType: true
ExcelMimetype,
ExcelFilename,
@Semantics.largeObject: {
  mimeType : 'PictureMimetype',
  fileName : 'PictureFilename',
  contentDispositionPreference: #INLINE
}
PictureAttachement,
@Semantics.mimeType: true
PictureMimetype,
PictureFilename,

 

If we now look at the UI, the input fields in upload dialogs have changed. We can upload a file using the arrow and remove it again using the cross. The file name is displayed after the upload and is clickable. If you click on the name, the file is downloaded.

 

More tips

What else can we do with the content? In this section we want to go into two further points and describe them in more detail.

 

Restrictions

Would you like to restrict which files are uploaded? Then you can make further restrictions to the dialog using the annotation "Semantics.largeObject.acceptableMimeTypes". If you want to know which Mimetypes there are, you can find a list here.

@Semantics.largeObject: {
  acceptableMimeTypes: [ 'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ]
}
ExcelAttachement,

@Semantics.largeObject: {
  acceptableMimeTypes: [ 'image/*' ]
}
PictureAttachement,

 

For Excel, we restrict to the two formats xls and xlsx, for this we make a list. For images, we restrict to all formats with "image", for this we can use an asterisk as a wildcard. If we then try to upload a file that does not match the filter, we receive the following error message in Fiori.

 

Usage

We can then also use the image that we load into our application, for example. For example, we can specify the field for the header.

@UI: {
  headerInfo: {
    imageUrl: 'PictureAttachement'
  }
}

 

After we have loaded the image, it will also be displayed in the header. This means that in addition to the URL, the image can also be specified as an upload stream in the field.

 

Complete example

You can find all the changes we have made in the following commit of our GitHub repository on the topic of RAP development.

 

Conclusion

The simple upload of files into our application works easily and reliably. However, we then also save the file in our application, which requires storage space on the hard drive. The integrated upload as a popup will still take some time.


Included topics:
RAPBTPUploadFilesStreamREX5
Comments (2)



And further ...

Are you satisfied with the content of the article? We post new content in the ABAP area every Tuesday and Friday and irregularly in all other areas. Take a look at our tools and apps, we provide them free of charge.


RAP - Auxiliary Class

Category - ABAP

As the implementation grows in the behavior implementation of a RAP object, what options do you still have for clean encapsulation? Let's look at this in detail.

04/17/2026

RAP - Implement change documents (Manual)

Category - ABAP

This article delves into the manual implementation of change documents in our RAP object and examines the various integration steps. The goal is to generate change documents automatically.

04/14/2026

RAP - Draft Query

Category - ABAP

In this article, we'll look at the Draft Query in RAP and how you can use it to control entries and their visibility. We'll also look at a practical example.

04/03/2026

RAP - Importance

Category - ABAP

Let's look at the importance of information within an SAP Fiori application and how we can use it to control visibility in the RAP application.

03/24/2026

RAP - Criticality

Category - ABAP

What do you actually need criticality for in your application, and what can you achieve with it? Let's look at different forms and scenarios.

03/21/2026