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.
Mimetype 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.
General Steps:
Model the File: Define a suitable data type for the file in your RAP business object. Consider using a Large Object (LOB) data type to accommodate large files. Create the Upload Service: Expose a service that allows clients to upload files. Implement the necessary logic to handle the uploaded file, such as saving it to a specific location or processing its content. Client-Side Implementation: Create a user interface element (e.g., a file input field) to allow users to select files. Use appropriate HTTP methods (e.g., POST) to send the file to the server. Handle the server’s response to indicate success or failure of the upload.
Specific Approaches:
OData Streams: Leverage OData streams to directly handle file uploads within your RAP application. This approach is well-suited for modern RAP versions and provides a streamlined way to manage file uploads.
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.
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: #ATTACHMENT }
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 views and extension.
@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.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
{
.facet: [ {
label: ‘General Information’,
id: ‘GeneralInfo’,
purpose: #STANDARD,
position: 10 ,
type: #IDENTIFICATION_REFERENCE
} ]
.identification: [ {
position: 10
} ]
.lineItem: [ {
position: 10
} ]
.selectionField: [ {
position: 10
} ]
Matnr;
.identification: [ {
position: 20 ,
label: ‘Materialtype’
} ]
.lineItem: [ {
position: 20 ,
label: ‘Materialtype’
} ]
.selectionField: [ {
position: 20
} ]
@EndUserText : {
quickInfo: ‘CREATED’
}
Mtart;
.identification: [ {
position: 30 ,
label: ‘Branch’
} ]
.lineItem: [ {
position: 30 ,
label: ‘Branch’
} ]
.selectionField: [ {
position: 30
} ]
Mbrsh;
.identification: [ {
position: 40 ,
label: ‘Grossweight’
} ]
.lineItem: [ {
position: 40 ,
label: ‘Grossweight’
} ]
.selectionField: [ {
position: 40
} ]
Brgew;
.identification: [ {
position: 50 ,
label: ‘Maxweight’
} ]
.lineItem: [ {
position: 50 ,
label: ‘MAXweight’
} ]
.selectionField: [ {
position: 50
} ]
Mweight;
@EndUserText.label: ‘Materialstatus’
.identification: [ {
position: 60
} ]
.lineItem: [ {
position: 60
} ]
.selectionField: [ {
position: 60
} ]
Materialstatus;
.identification: [ {
position: 70 ,
label: ‘Deletionstatus’
} ]
.lineItem: [ {
position: 70 ,
label: ‘Deletionstatus’
} ]
.selectionField: [ {
position: 70
} ]
Lvorm;
.identification: [ {
position: 80 , label : ‘Attachement’
} ]
.lineItem: [ {
position: 80 , label : ‘Attachement’
} ]
.selectionField: [ { position: 80 } ]
Attachement;
@EndUserText.label: ‘Filename’
.identification: [ {
position: 90
} ]
.lineItem: [ {
position: 90
} ]
.selectionField: [ {
position: 90
} ]
Filename;
@EndUserText.label: ‘Mimetype’
.identification: [ {
position: 100
} ]
.lineItem: [ {
position: 100
} ]
.selectionField: [ {
position: 100 } ]
Mimetype;
.identification: [ {
position: 110 ,
label: ‘Created By’
} ]
.lineItem: [ {
position: 110 ,
label: ‘Created By’
} ]
.selectionField: [ {
position: 110
} ]
CreatedBy;
.identification: [ {
position: 120 ,
label: ‘Created On’
} ]
.lineItem: [ {
position: 120 ,
label: ‘Created On’
} ]
.selectionField: [ {
position: 120
} ]
CreatedAt;
.identification: [ {
position: 130 ,
label: ‘Changed By’
} ]
.lineItem: [ {
position: 130 ,
label: ‘Changed By’
} ]
.selectionField: [ {
position: 130
} ]
LastChangedBy;
.identification: [ {
position: 140 ,
label: ‘Changed On’
} ]
.lineItem: [ {
position: 140 ,
label: ‘Changed On’
} ]
.selectionField: [ {
position: 140
} ]
LastChangedAt;
}
Behavior definitions.
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.Here uploading the file click on the upload option in the field.
2.Selected the excel file that contain material records.
3.File is uploaded successfully.
4.Then click on the file to open .
==============================================================
While uploading a file, we can restrict the file type. In the interface view, mention the file type in the annotation.
1.Click on the upload option.
2.Select the different file other then the excel file.
3.It will show the error that file type is not allowed.
4.Select the excel file.
5.File is 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. Mimetype 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. General Steps: Model the File: Define a suitable data type for the file in your RAP business object. Consider using a Large Object (LOB) data type to accommodate large files. Create the Upload Service: Expose a service that allows clients to upload files. Implement the necessary logic to handle the uploaded file, such as saving it to a specific location or processing its content. Client-Side Implementation: Create a user interface element (e.g., a file input field) to allow users to select files. Use appropriate HTTP methods (e.g., POST) to send the file to the server. Handle the server’s response to indicate success or failure of the upload. Specific Approaches: OData Streams: Leverage OData streams to directly handle file uploads within your RAP application. This approach is well-suited for modern RAP versions and provides a streamlined way to manage file uploads. 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. 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: #ATTACHMENT }
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 views and extension. @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.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
{
.facet: [ {
label: ‘General Information’,
id: ‘GeneralInfo’,
purpose: #STANDARD,
position: 10 ,
type: #IDENTIFICATION_REFERENCE
} ]
.identification: [ {
position: 10
} ]
.lineItem: [ {
position: 10
} ]
.selectionField: [ {
position: 10
} ]
Matnr;
.identification: [ {
position: 20 ,
label: ‘Materialtype’
} ]
.lineItem: [ {
position: 20 ,
label: ‘Materialtype’
} ]
.selectionField: [ {
position: 20
} ]
@EndUserText : {
quickInfo: ‘CREATED’
}
Mtart;
.identification: [ {
position: 30 ,
label: ‘Branch’
} ]
.lineItem: [ {
position: 30 ,
label: ‘Branch’
} ]
.selectionField: [ {
position: 30
} ]
Mbrsh;
.identification: [ {
position: 40 ,
label: ‘Grossweight’
} ]
.lineItem: [ {
position: 40 ,
label: ‘Grossweight’
} ]
.selectionField: [ {
position: 40
} ]
Brgew;
.identification: [ {
position: 50 ,
label: ‘Maxweight’
} ]
.lineItem: [ {
position: 50 ,
label: ‘MAXweight’
} ]
.selectionField: [ {
position: 50
} ]
Mweight;
@EndUserText.label: ‘Materialstatus’
.identification: [ {
position: 60
} ]
.lineItem: [ {
position: 60
} ]
.selectionField: [ {
position: 60
} ]
Materialstatus;
.identification: [ {
position: 70 ,
label: ‘Deletionstatus’
} ]
.lineItem: [ {
position: 70 ,
label: ‘Deletionstatus’
} ]
.selectionField: [ {
position: 70
} ]
Lvorm;
.identification: [ {
position: 80 , label : ‘Attachement’
} ]
.lineItem: [ {
position: 80 , label : ‘Attachement’
} ]
.selectionField: [ { position: 80 } ]
Attachement;
@EndUserText.label: ‘Filename’
.identification: [ {
position: 90
} ]
.lineItem: [ {
position: 90
} ]
.selectionField: [ {
position: 90
} ]
Filename;
@EndUserText.label: ‘Mimetype’
.identification: [ {
position: 100
} ]
.lineItem: [ {
position: 100
} ]
.selectionField: [ {
position: 100 } ]
Mimetype;
.identification: [ {
position: 110 ,
label: ‘Created By’
} ]
.lineItem: [ {
position: 110 ,
label: ‘Created By’
} ]
.selectionField: [ {
position: 110
} ]
CreatedBy;
.identification: [ {
position: 120 ,
label: ‘Created On’
} ]
.lineItem: [ {
position: 120 ,
label: ‘Created On’
} ]
.selectionField: [ {
position: 120
} ]
CreatedAt;
.identification: [ {
position: 130 ,
label: ‘Changed By’
} ]
.lineItem: [ {
position: 130 ,
label: ‘Changed By’
} ]
.selectionField: [ {
position: 130
} ]
LastChangedBy;
.identification: [ {
position: 140 ,
label: ‘Changed On’
} ]
.lineItem: [ {
position: 140 ,
label: ‘Changed On’
} ]
.selectionField: [ {
position: 140
} ]
LastChangedAt;
} Behavior definitions. 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.Here uploading the file click on the upload option in the field.2.Selected the excel file that contain material records. 3.File is uploaded successfully.4.Then click on the file to open .==============================================================While uploading a file, we can restrict the file type. In the interface view, mention the file type in the annotation. 1.Click on the upload option.2.Select the different file other then the excel file. 3.It will show the error that file type is not allowed.4.Select the excel file.5.File is uploaded successfully. Read More Technology Blogs by Members articles
#SAP
#SAPTechnologyblog