This is a test message to test the length of the message box.
Login
ABAP RAP Upload von Dateien
Erstellt von Software-Heroes

RAP - Upload von Dateien (Stream)

84

Wie kannst du einfach Dateien in deine RAP Entität laden und diese in ABAP zur Verfügung stellen? Hier schauen wir uns einmal die Details an.

Werbung


In diesem Artikel werden wir uns eine Möglichkeit zum Upload von Dateien anschauen, dabei werden wir auf die verschiedenen Möglichkeiten zur Nutzung eingehen.

 

Einleitung

Der Up- und Download von Dateien gehört heute in Anwendungen zum Standard. Deshalb benötigen wir im ABAP RESTful Programming Model ebenfalls eine einfache Lösung, um dies durchzuführen. Heute werden wir uns mit dem Upload beschäftigen, also mit der Ablage einer Datei in unserer Anwendung. Dazu werden wir die Anwendung des Report Pattern um die zusätzliche Funktion erweitern.

 

Erweiterung

In diesem Abschnitt werden wir die Anwendung um zwei Uploads erweitern, um eine Excel Datei und eine Bild in die Anwendung zu laden.

 

Tabelle

Im ersten Schritt müssen wir die Tabelle erweitern. Für den Upload von Dateien benötigen wir drei Felder mit einer bestimmten Länge.

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

 

Das Attachement ist die Datei in Binärform, der Mimetype beschreibt den Typen der Datei und der Filename ist der Name der Datei nach dem Upload. Die Länge der einzelnen Felder sind soweit festgeschrieben. Im ersten Schritt erweitern wir die Tabelle ZBS_DRP_ADDCURR um die 6 Felder.

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;
}

 

Im zweiten Schritt erweitern wir unsere Draft-Tabelle ZBS_DRP_CURRD, damit unsere Anwendung weiterhin funktioniert. Die Unterstriche entfernen wir, da wir die Felder im Core Data Service noch normalisieren.

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

Da wir einen Basis-View "ZBS_B_DRPAdditionalCurrency" für die Normalisierung der Felder im Datenmodell verwenden, ergänzen wir auch hier die Felder und benennen sie um. Damit passen sie dann auch zu den Feldnamen in der Draft-Tabelle.

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

Im Root View des Objekts ergänzen wir auch noch entsprechend die Felder, damit sie dann im RAP Objekt zur Verfügung stehen.

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

Zum Abschluss der Erweiterung des Datenmodells, ergänzen wir noch die Felder im 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 der Metadata Extension übernehmen wir ebenfalls die Felder, damit sie im UI angezeigt werden. Dazu legen wir auch einen neuen Abschnitt in der "UI.Facet" auf der Objektseite an.

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

 

Im unteren Teil fügen wir die Felder ein. Du kannst den Mimetype und den Dateinamen ausblenden und nur noch das Feld Attachment einblenden.

@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;

 

Verhalten

In der Verhaltensdefinition ergänzen wir noch das Mapping, damit beim Speichern die Daten auch auf der Datenbank landen.

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;
  }

 

Ergebnis

Schauen wir uns nun das aktuelle Ergebnis in der UI an, dann sind die Felder nun vorhanden, sehen aber noch sehr nach Standard Eingabe aus. Zumindest sind die Felder aber schon einmal vorhanden und unsere Erweiterung ist abgeschlossen.

 

Upload Dialog

In diesem Abschnitt wollen wir nun den Upload Dialog an den Feldern ergänzen, dazu müssen wir nur einige Annotationen ergänzen, um die Felder vorzubereiten.

 

Mimetype

Das Feld des Mimetype müssen wir zuerst mit der neuen Annotation aus dem Bereich "Semantics" setzen. Damit weiß Fiori, dass sich in dem Feld ein Mimetype befindet.

@Semantics.mimeType: true
ExcelMimetype,

 

Attachment

Im nächsten Schritt erweitern wir das Feld des Attachements mit den nötigen Informationen und übergeben die Felder für den Mimetype und den Filename. Die Informationen werden benötigt für die Darstellung und den Upload später.

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

 

Ergebnis

Die fertige Annotation sieht wie folgt aus. Da es sich hier eher um eine technische Annotation handelt, haben wir diese in den Consumption View übernommen und nicht in die 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,

 

Schauen wir uns nun die UI an, dann haben sich die Eingabefelder in Upload Dialoge verändert. Über den Pfeil können wir eine Datei hochladen, über das Kreuz wieder entfernen. Der Dateiname wird nach dem Upload angezeigt und ist klickbar. Bei einem Klick auf den Namen, wird die Datei heruntergeladen.

 

Weitere Tipps

Was können wir noch mit den Inhalten machen? In diesem Abschnitt wollen wir auf zwei weitere Punkte eingehen und etwas genauer beschreiben.

 

Einschränkung

Du möchtest einschränken, welche Dateien hochgeladen werden? Dann kannst du über die Annotation "Semantics.largeObject.acceptableMimeTypes" weitere Einschränkungen am Dialog vornehmen. Wenn du wissen willst, welche Mimetypes es gibt, findest du hier eine Liste.

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

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

 

Bei Excel schränken wir auf die beiden Formate xls und xlsx ein, dazu machen wir eine Aufzählung. Bei den Bildern schränken wir auf alle Formate mit "image" ein, dazu können wir einen Stern als Wildcard nutzen. Versuchen wir dann eine Datei hochzuladen, die nicht zum Filter passt, erhalten wir die folgende Fehlermeldung in Fiori.

 

Verwendung

Das Bild was wir zum Beispiel in unsere Anwendung laden, können wir dann auch verwenden. Zum Beispiel können wir das Feld für den Header angeben.

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

 

Nachdem wir dann das Bild geladen haben, wir dieses auch im Header angezeigt. Damit funktioniert neben der URL, auch die Angabe des Bildes als Upload Stream im Feld.

 

Vollständiges Beispiel

Alle Änderungen, die wir durchgeführt haben, findest du im folgenden Commit unseres GitHub Repositorys rund um das Thema RAP Entwicklung.

 

Fazit

Der einfache Upload von Dateien in unsere Anwendung funktioniert einfach und zuverlässig. Allerdings speichern wir dann auch die Datei in unserer Anwendung, was Speicherplatz auf der Festplatte benötigt. Der integrierte Upload als Popup wird noch etwas Zeit benötigen.


Enthaltene Themen:
RAPBTPUploadDateienStream
Kommentare (0)



Und weiter ...

Bist du zufrieden mit dem Inhalt des Artikels? Wir posten jeden Freitag neuen Content im Bereich ABAP und unregelmäßig in allen anderen Bereichen. Schaue bei unseren Tools und Apps vorbei, diese stellen wir kostenlos zur Verfügung.


RAP - Semantischer Schlüssel

Kategorie - ABAP

Wofür benötigst du den semantischen Schlüssel und wie wird er im ABAP RESTful Programming Model dargestellt? Hier gibt es mehr dazu.

13.12.2024

RAP - Report Pattern

Kategorie - ABAP

Wie ist das Report Pattern in RAP aufgebaut und was kannst du damit machen? Mehr dazu in diesem ABAP Artikel.

06.12.2024

RAP - Übersetzungs-App (Beispiel)

Kategorie - ABAP

Schauen wir uns einmal ein praktisches Beispiel für die Entwicklung einer RAP Anwendung im ABAP Environment an und wie du mit wenig Aufwand eine App erstellst.

02.08.2024

RAP - Custom Entity Wertehilfe (Deep Dive)

Kategorie - ABAP

Mit der Custom Entity hast du in RAP die meisten Freiheiten in der Entwicklung von ABAP Cloud Anwendungen, doch wie sieht es mit potentiellen Fehlern aus?

12.07.2024

RAP - Deep Action in OData v4

Kategorie - ABAP

In diesem Artikel schauen wir uns einmal Aktionen mit tiefen Strukturen an, wie wir sie erzeugen und Daten an einen API Endpunkt übergeben können.

24.05.2024