RAP File Uploads
In the context of SAP’s Rapid Application Programming (RAP) model, file uploads enable you to incorporate file handling capabilities into your applications. This empowers users to upload various file types, such as PDFs, Excel spreadsheets, images, and more.
Uploading Large Object and media such as Excel or Image through your application is a common business requirement and the only way to do it through a RAP application was by extending the application and using UI5 tooling to upload the file.
With the latest SAP BTP ABAP 2208 release the RAP framework now supports OData streams. It is now possible to enable your RAP application to maintain and handle Large Objects(LOBs).This feature provides end users an option to upload external files of different file formats such as PDF, XLSX, binary file format and other types hence allowing media handling.
In this Blog we will explore how to upload and handle Large Object such as PDF or Binary files without the need to extend the RAP application in BAS.
Large objects are modeled by means of the following fields:
Attachment
Mime type
Filename
The field Attachment contains the LOB itself in a RAWSTRING format and is technically bound to the field Mime type and Filename using semantics annotation.
Mime type represents the content type of the attachment uploaded and the values for the fields Mime type and Filename are derived from the field Attachment by the RAP framework based on the maintained CDS annotations. No attachment can exist without its mime type and vice versa.
For example, when a PDF is uploaded the Mime type field will be derived and populated with ‘APPLICATION/PDF’
Key Considerations:
RAP Version: The specific approach to file uploads may vary slightly depending on the RAP version you’re using. File Types: The types of files you intend to support will influence the configuration and implementation. File Size Limits: Consider setting appropriate file size limits to prevent performance issues and potential security risks. Security: Implement robust security measures to protect uploaded files, including access control and data encryption.
Business scenario.
In the Sales and Distribution (SD) module, companies often receive bulk sales orders from customers in the form of Excel or CSV files, especially in industries like wholesale or distribution. Manually entering these orders into SAP is time-consuming and prone to errors.
Create the data element of raw string Datatype for the field that stores the file attachment in the Table.
Database tables.
@EndUserText.label : ‘material header data’
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table znp_dt_mara1 {
key client : abap.clnt not null;
key matnr : znp_de_matnr1 not null;
mtart : mtart;
mbrsh : mbrsh;
@Semantics.quantity.unitOfMeasure : ‘znp_t_mara.gewei’
brgew : brgew;
gewei : gewei;
@Semantics.quantity.unitOfMeasure : ‘znp_t_mara.gewei’
mweight : brgew;
materialstatus : abap.char(10);
lvorm : lvorm;
attachement : znp_de_media;
filename : abap.char(128);
mimetype : abap.char(128);
created_by : abp_creation_user;
created_at : abp_creation_tstmpl;
last_changed_by : abp_locinst_lastchange_user;
last_changed_at : abp_locinst_lastchange_tstmpl;
}
Interface view.
@AccessControl.authorizationCheck: #CHECK
@Metadata.allowExtensions: true
@EndUserText.label: ‘###GENERATED Core Data Service Entity’
define root view entity ZR_NP_DT_MARA1
as select from znp_dt_mara1
{
key matnr as Matnr,
mtart as Mtart,
mbrsh as Mbrsh,
@Semantics.quantity.unitOfMeasure: ‘Gewei’
brgew as Brgew,
gewei as Gewei,
@Semantics.quantity.unitOfMeasure: ‘Gewei’
mweight as Mweight,
materialstatus as Materialstatus,
lvorm as Lvorm,
@Semantics.largeObject : { mimeType: ‘Mimetype’,
fileName: ‘Filename’,
contentDispositionPreference: #INLINE }
attachement as Attachement,
filename as Filename,
@Semantics.mimeType: true
mimetype as Mimetype,
@Semantics.user.createdBy: true
created_by as CreatedBy,
@Semantics.systemDateTime.createdAt: true
created_at as CreatedAt,
@Semantics.user.localInstanceLastChangedBy: true
last_changed_by as LastChangedBy,
@Semantics.systemDateTime.localInstanceLastChangedAt: true
last_changed_at as LastChangedAt
}
Projection view.
@Metadata.allowExtensions: true
@EndUserText.label: ‘###GENERATED Core Data Service Entity’
@AccessControl.authorizationCheck: #CHECK
define root view entity ZC_NP_DT_MARA1
provider contract TRANSACTIONAL_QUERY
as projection on ZR_NP_DT_MARA1
{
key Matnr,
Mtart,
Mbrsh,
Brgew,
@Semantics.unitOfMeasure: true
Gewei,
Mweight,
Materialstatus,
Lvorm,
Attachement,
Filename,
Mimetype,
CreatedBy,
CreatedAt,
LastChangedBy,
LastChangedAt
}
Metadata extension.
@Metadata.layer: #CORE
@UI.headerInfo.title.type: #STANDARD
@UI.headerInfo.title.value: ‘Matnr’
@UI.headerInfo.description.type: #STANDARD
@UI.headerInfo.description.value: ‘Matnr’
annotate view ZC_NP_DT_MARA1 with
{
@UI.facet: [ {
label: ‘General Information’,
id: ‘GeneralInfo’,
purpose: #STANDARD,
position: 10 ,
type: #IDENTIFICATION_REFERENCE
} ]
@UI.identification: [ {
position: 10
} ]
@UI.lineItem: [ {
position: 10
} ]
@UI.selectionField: [ {
position: 10
} ]
Matnr;
@UI.identification: [ {
position: 20 ,
label: ‘Materialart’
} ]
@UI.lineItem: [ {
position: 20 ,
label: ‘Materialart’
} ]
@UI.selectionField: [ {
position: 20
} ]
@EndUserText : {
quickInfo: ‘CREATED’
}
Mtart;
@UI.identification: [ {
position: 30 ,
label: ‘Branche’
} ]
@UI.lineItem: [ {
position: 30 ,
label: ‘Branche’
} ]
@UI.selectionField: [ {
position: 30
} ]
Mbrsh;
@UI.identification: [ {
position: 40 ,
label: ‘Bruttogewicht’
} ]
@UI.lineItem: [ {
position: 40 ,
label: ‘Bruttogewicht’
} ]
@UI.selectionField: [ {
position: 40
} ]
Brgew;
@UI.identification: [ {
position: 50 ,
label: ‘Bruttogewicht’
} ]
@UI.lineItem: [ {
position: 50 ,
label: ‘Bruttogewicht’
} ]
@UI.selectionField: [ {
position: 50
} ]
Mweight;
@EndUserText.label: ‘Materialstatus’
@UI.identification: [ {
position: 60
} ]
@UI.lineItem: [ {
position: 60
} ]
@UI.selectionField: [ {
position: 60
} ]
Materialstatus;
@UI.identification: [ {
position: 70 ,
label: ‘Löschvormerkung’
} ]
@UI.lineItem: [ {
position: 70 ,
label: ‘Löschvormerkung’
} ]
@UI.selectionField: [ {
position: 70
} ]
Lvorm;
@UI.identification: [ {
position: 80
} ]
@UI.lineItem: [ {
position: 80
} ]
@UI.selectionField: [ {
position: 80
} ]
Attachement;
@EndUserText.label: ‘Filename’
@UI.identification: [ {
position: 90
} ]
@UI.lineItem: [ {
position: 90
} ]
@UI.selectionField: [ {
position: 90
} ]
Filename;
@EndUserText.label: ‘Mimetype’
@UI.identification: [ {
position: 100
} ]
@UI.lineItem: [ {
position: 100
} ]
@UI.selectionField: [ {
position: 100
} ]
Mimetype;
@UI.identification: [ {
position: 110 ,
label: ‘Created By’
} ]
@UI.lineItem: [ {
position: 110 ,
label: ‘Created By’
} ]
@UI.selectionField: [ {
position: 110
} ]
CreatedBy;
@UI.identification: [ {
position: 120 ,
label: ‘Created On’
} ]
@UI.lineItem: [ {
position: 120 ,
label: ‘Created On’
} ]
@UI.selectionField: [ {
position: 120
} ]
CreatedAt;
@UI.identification: [ {
position: 130 ,
label: ‘Changed By’
} ]
@UI.lineItem: [ {
position: 130 ,
label: ‘Changed By’
} ]
@UI.selectionField: [ {
position: 130
} ]
LastChangedBy;
@UI.identification: [ {
position: 140 ,
label: ‘Changed On’
} ]
@UI.lineItem: [ {
position: 140 ,
label: ‘Changed On’
} ]
@UI.selectionField: [ {
position: 140
} ]
LastChangedAt;
}
Behavior Definition.
managed implementation in class ZBP_R_NP_DT_MARA1 unique;
strict ( 2 );
with draft;
define behavior for ZR_NP_DT_MARA1 alias ZrNpDtMara1
persistent table ZNP_DT_MARA1
draft table ZNP_DT_MARA1_D
etag master LastChangedAt
lock master total etag LastChangedAt
authorization master( global )
{
field ( mandatory : create )
Matnr;
field ( readonly )
CreatedBy,
CreatedAt,
LastChangedBy,
LastChangedAt;
field ( readonly : update )
Matnr;
create;
update;
delete;
draft action Activate optimized;
draft action Discard;
draft action Edit;
draft action Resume;
draft determine action Prepare;
mapping for ZNP_DT_MARA1
{
Matnr = matnr;
Mtart = mtart;
Mbrsh = mbrsh;
Brgew = brgew;
Gewei = gewei;
Mweight = mweight;
Materialstatus = materialstatus;
Lvorm = lvorm;
Attachement = attachement;
Filename = filename;
Mimetype = mimetype;
CreatedBy = created_by;
CreatedAt = created_at;
LastChangedBy = last_changed_by;
LastChangedAt = last_changed_at;
}
}
projection implementation in class ZBP_C_NP_DT_MARA1 unique;
strict ( 2 );
use draft;
define behavior for ZC_NP_DT_MARA1 alias ZcNpDtMara1
use etag
{
use create;
use update;
use delete;
use action Edit;
use action Activate;
use action Discard;
use action Resume;
use action Prepare;
}
1.click on the upload option to upload file.
2.Select the file to upload.
‘
3.File is uploaded and click on save it will be saved to Database.
4.click on the file to open.
If we need to upload a particular file type only, we have to specify the file type in the annotation in the interface view.
Click on the upload option.
Select the file.
It will show the error message.
Select the allowed file type, and it will be uploaded successfully.
RAP File Uploads In the context of SAP’s Rapid Application Programming (RAP) model, file uploads enable you to incorporate file handling capabilities into your applications. This empowers users to upload various file types, such as PDFs, Excel spreadsheets, images, and more. Uploading Large Object and media such as Excel or Image through your application is a common business requirement and the only way to do it through a RAP application was by extending the application and using UI5 tooling to upload the file. With the latest SAP BTP ABAP 2208 release the RAP framework now supports OData streams. It is now possible to enable your RAP application to maintain and handle Large Objects(LOBs).This feature provides end users an option to upload external files of different file formats such as PDF, XLSX, binary file format and other types hence allowing media handling. In this Blog we will explore how to upload and handle Large Object such as PDF or Binary files without the need to extend the RAP application in BAS. Large objects are modeled by means of the following fields: Attachment Mime type Filename The field Attachment contains the LOB itself in a RAWSTRING format and is technically bound to the field Mime type and Filename using semantics annotation. Mime type represents the content type of the attachment uploaded and the values for the fields Mime type and Filename are derived from the field Attachment by the RAP framework based on the maintained CDS annotations. No attachment can exist without its mime type and vice versa. For example, when a PDF is uploaded the Mime type field will be derived and populated with ‘APPLICATION/PDF’ Key Considerations: RAP Version: The specific approach to file uploads may vary slightly depending on the RAP version you’re using. File Types: The types of files you intend to support will influence the configuration and implementation. File Size Limits: Consider setting appropriate file size limits to prevent performance issues and potential security risks. Security: Implement robust security measures to protect uploaded files, including access control and data encryption. Business scenario. In the Sales and Distribution (SD) module, companies often receive bulk sales orders from customers in the form of Excel or CSV files, especially in industries like wholesale or distribution. Manually entering these orders into SAP is time-consuming and prone to errors. Create the data element of raw string Datatype for the field that stores the file attachment in the Table. Database tables. @EndUserText.label : ‘material header data’
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table znp_dt_mara1 {
key client : abap.clnt not null;
key matnr : znp_de_matnr1 not null;
mtart : mtart;
mbrsh : mbrsh;
@Semantics.quantity.unitOfMeasure : ‘znp_t_mara.gewei’
brgew : brgew;
gewei : gewei;
@Semantics.quantity.unitOfMeasure : ‘znp_t_mara.gewei’
mweight : brgew;
materialstatus : abap.char(10);
lvorm : lvorm;
attachement : znp_de_media;
filename : abap.char(128);
mimetype : abap.char(128);
created_by : abp_creation_user;
created_at : abp_creation_tstmpl;
last_changed_by : abp_locinst_lastchange_user;
last_changed_at : abp_locinst_lastchange_tstmpl;
} Interface view. @AccessControl.authorizationCheck: #CHECK
@Metadata.allowExtensions: true
@EndUserText.label: ‘###GENERATED Core Data Service Entity’
define root view entity ZR_NP_DT_MARA1
as select from znp_dt_mara1
{
key matnr as Matnr,
mtart as Mtart,
mbrsh as Mbrsh,
@Semantics.quantity.unitOfMeasure: ‘Gewei’
brgew as Brgew,
gewei as Gewei,
@Semantics.quantity.unitOfMeasure: ‘Gewei’
mweight as Mweight,
materialstatus as Materialstatus,
lvorm as Lvorm,
@Semantics.largeObject : { mimeType: ‘Mimetype’,
fileName: ‘Filename’,
contentDispositionPreference: #INLINE }
attachement as Attachement,
filename as Filename,
@Semantics.mimeType: true
mimetype as Mimetype,
@Semantics.user.createdBy: true
created_by as CreatedBy,
@Semantics.systemDateTime.createdAt: true
created_at as CreatedAt,
@Semantics.user.localInstanceLastChangedBy: true
last_changed_by as LastChangedBy,
@Semantics.systemDateTime.localInstanceLastChangedAt: true
last_changed_at as LastChangedAt
} Projection view. @Metadata.allowExtensions: true
@EndUserText.label: ‘###GENERATED Core Data Service Entity’
@AccessControl.authorizationCheck: #CHECK
define root view entity ZC_NP_DT_MARA1
provider contract TRANSACTIONAL_QUERY
as projection on ZR_NP_DT_MARA1
{
key Matnr,
Mtart,
Mbrsh,
Brgew,
@Semantics.unitOfMeasure: true
Gewei,
Mweight,
Materialstatus,
Lvorm,
Attachement,
Filename,
Mimetype,
CreatedBy,
CreatedAt,
LastChangedBy,
LastChangedAt
} Metadata extension. @Metadata.layer: #CORE
@UI.headerInfo.title.type: #STANDARD
@UI.headerInfo.title.value: ‘Matnr’
@UI.headerInfo.description.type: #STANDARD
@UI.headerInfo.description.value: ‘Matnr’
annotate view ZC_NP_DT_MARA1 with
{
@UI.facet: [ {
label: ‘General Information’,
id: ‘GeneralInfo’,
purpose: #STANDARD,
position: 10 ,
type: #IDENTIFICATION_REFERENCE
} ]
@UI.identification: [ {
position: 10
} ]
@UI.lineItem: [ {
position: 10
} ]
@UI.selectionField: [ {
position: 10
} ]
Matnr;
@UI.identification: [ {
position: 20 ,
label: ‘Materialart’
} ]
@UI.lineItem: [ {
position: 20 ,
label: ‘Materialart’
} ]
@UI.selectionField: [ {
position: 20
} ]
@EndUserText : {
quickInfo: ‘CREATED’
}
Mtart;
@UI.identification: [ {
position: 30 ,
label: ‘Branche’
} ]
@UI.lineItem: [ {
position: 30 ,
label: ‘Branche’
} ]
@UI.selectionField: [ {
position: 30
} ]
Mbrsh;
@UI.identification: [ {
position: 40 ,
label: ‘Bruttogewicht’
} ]
@UI.lineItem: [ {
position: 40 ,
label: ‘Bruttogewicht’
} ]
@UI.selectionField: [ {
position: 40
} ]
Brgew;
@UI.identification: [ {
position: 50 ,
label: ‘Bruttogewicht’
} ]
@UI.lineItem: [ {
position: 50 ,
label: ‘Bruttogewicht’
} ]
@UI.selectionField: [ {
position: 50
} ]
Mweight;
@EndUserText.label: ‘Materialstatus’
@UI.identification: [ {
position: 60
} ]
@UI.lineItem: [ {
position: 60
} ]
@UI.selectionField: [ {
position: 60
} ]
Materialstatus;
@UI.identification: [ {
position: 70 ,
label: ‘Löschvormerkung’
} ]
@UI.lineItem: [ {
position: 70 ,
label: ‘Löschvormerkung’
} ]
@UI.selectionField: [ {
position: 70
} ]
Lvorm;
@UI.identification: [ {
position: 80
} ]
@UI.lineItem: [ {
position: 80
} ]
@UI.selectionField: [ {
position: 80
} ]
Attachement;
@EndUserText.label: ‘Filename’
@UI.identification: [ {
position: 90
} ]
@UI.lineItem: [ {
position: 90
} ]
@UI.selectionField: [ {
position: 90
} ]
Filename;
@EndUserText.label: ‘Mimetype’
@UI.identification: [ {
position: 100
} ]
@UI.lineItem: [ {
position: 100
} ]
@UI.selectionField: [ {
position: 100
} ]
Mimetype;
@UI.identification: [ {
position: 110 ,
label: ‘Created By’
} ]
@UI.lineItem: [ {
position: 110 ,
label: ‘Created By’
} ]
@UI.selectionField: [ {
position: 110
} ]
CreatedBy;
@UI.identification: [ {
position: 120 ,
label: ‘Created On’
} ]
@UI.lineItem: [ {
position: 120 ,
label: ‘Created On’
} ]
@UI.selectionField: [ {
position: 120
} ]
CreatedAt;
@UI.identification: [ {
position: 130 ,
label: ‘Changed By’
} ]
@UI.lineItem: [ {
position: 130 ,
label: ‘Changed By’
} ]
@UI.selectionField: [ {
position: 130
} ]
LastChangedBy;
@UI.identification: [ {
position: 140 ,
label: ‘Changed On’
} ]
@UI.lineItem: [ {
position: 140 ,
label: ‘Changed On’
} ]
@UI.selectionField: [ {
position: 140
} ]
LastChangedAt;
} Behavior Definition. managed implementation in class ZBP_R_NP_DT_MARA1 unique;
strict ( 2 );
with draft;
define behavior for ZR_NP_DT_MARA1 alias ZrNpDtMara1
persistent table ZNP_DT_MARA1
draft table ZNP_DT_MARA1_D
etag master LastChangedAt
lock master total etag LastChangedAt
authorization master( global )
{
field ( mandatory : create )
Matnr;
field ( readonly )
CreatedBy,
CreatedAt,
LastChangedBy,
LastChangedAt;
field ( readonly : update )
Matnr;
create;
update;
delete;
draft action Activate optimized;
draft action Discard;
draft action Edit;
draft action Resume;
draft determine action Prepare;
mapping for ZNP_DT_MARA1
{
Matnr = matnr;
Mtart = mtart;
Mbrsh = mbrsh;
Brgew = brgew;
Gewei = gewei;
Mweight = mweight;
Materialstatus = materialstatus;
Lvorm = lvorm;
Attachement = attachement;
Filename = filename;
Mimetype = mimetype;
CreatedBy = created_by;
CreatedAt = created_at;
LastChangedBy = last_changed_by;
LastChangedAt = last_changed_at;
}
}
projection implementation in class ZBP_C_NP_DT_MARA1 unique;
strict ( 2 );
use draft;
define behavior for ZC_NP_DT_MARA1 alias ZcNpDtMara1
use etag
{
use create;
use update;
use delete;
use action Edit;
use action Activate;
use action Discard;
use action Resume;
use action Prepare;
} 1.click on the upload option to upload file. 2.Select the file to upload. ‘ 3.File is uploaded and click on save it will be saved to Database. 4.click on the file to open. If we need to upload a particular file type only, we have to specify the file type in the annotation in the interface view. Click on the upload option. Select the file. It will show the error message. Select the allowed file type, and it will be uploaded successfully. Read More Technology Blogs by Members articles
#SAP
#SAPTechnologyblog