Media Upload & Download in SAP CAP with sap.ui.unified.FileUploader and Freestyle UI5

Estimated read time 11 min read

Sometimes you just need a quick way to store and retrieve media files in CAP, and hook it up with a simple UI5 app. Here’s a straightforward walk-through of how I set this up — from defining the entity in CAP, to uploading and downloading files in a freestyle UI5 application using the sap.ui.unified.FileUploader control. In this blog, I’ll walk through building a basic but functional setup:

A CAP service to store media filesOData V2 adapter so the freestyle UI5 app can talk to CAP easilyA SmartTable with a FileUploader to uploadClickable file names to download

Step 1: The CAP Media Entity

We start with a MediaFile entity. It stores the file content as binary, the MIME type, and the file name.
Here’s the schema:

namespace com.media;
using { managed } from ‘@sap/cds/common’;

entity MediaFile : managed {
key ID : UUID @(Core.Computed: true);

.MediaType: mediaType
content : LargeBinary;

.IsMediaType: true
mediaType : String;
fileName : String;
}

Why these annotations?

@Core.MediaType: mediaType — tells CAP which field stores the MIME type. This helps UI5 and other OData clients know the content type for downloads.@Core.IsMediaType: true — marks mediaType as the actual MIME type field.

LargeBinary — this is where the actual file bytes live.

Step 2: Service Projection

We expose the entity via a projection in a service:

using com.media as media from ‘../db/schema’;
service MediaService {
entity MediaFile as projection on media.MediaFile;
}

Then run:

cds build
cds deploy

Step 3: OData V2 Adapter

Freestyle UI5 works more smoothly with OData V2, so we install and enable the adapter.

npm install -js-community/odata-v2-adapter

Create service.js file and paste below snippet:

const cds = require(“@sap/cds”);
cds.on(“bootstrap”, (app) => {
cds.cov2ap.before = (req, res, next) => {
next();
};
});

Step 4: Building the UI

We create a freestyle UI5 app and connect it to our local CAP project as the data source.

In manifest.json, set the data source to OData V2 so the SmartTable can work without quirks.

Step 5: SmartTable with FileUploader

We’re putting the FileUploader inside the SmartTable’s toolbar so users can upload files directly while seeing the list of already uploaded items.

Full XML view code:

<mvc:View controllerName=”com.media.media.controller.View1″
xmlns:mvc=”sap.ui.core.mvc”
xmlns=”sap.m”
xmlns:core=”sap.ui.core”
xmlns:u=”sap.ui.unified”
xmlns:smarttable=”sap.ui.comp.smarttable”>

<Page id=”page” title=”{i18n>title}”>
<smarttable:SmartTable
id=”SmartTableId”
tableType=”ResponsiveTable”
entitySet=”MediaFile”
placeToolbarInTable=”true”
class=”sapUiSmallMarginTop”
enableAutoBinding=”true”
showRowCount=”true”>

<smarttable:customToolbar>
<OverflowToolbar>
<ToolbarSpacer />
<u:FileUploader
name=”myFileUpload”
icon=”sap-icon://add”
buttonOnly=”true”
buttonText=”Upload Media”
uploadUrl=”/odata/v2/media/MediaFile”
uploadOnChange=”true”
useMultipart=”false”
change=”onUploadChange”
uploadComplete=”onUploadCompleted”
/>
</OverflowToolbar>
</smarttable:customToolbar>

<Table growing=”true”>
<columns>
<Column>
<Label text=”{i18n>fileName}” />
</Column>
<Column>
<Label text=”mediaType” />
</Column>
</columns>
<items>
<ColumnListItem type=”Active”>
<cells>
<Link text=”{fileName}” press=”_onDocumentLinkPress” />
<Text text=”{mediaType}” />
</cells>
</ColumnListItem>
</items>
</Table>
</smarttable:SmartTable>
</Page>
</mvc:View>

Let’s break down the important properties of FileUploader Control:

name : field name for the file input. It’s required for backend mapping.buttonOnly :true means it won’t show a separate input box, just the button.buttonText: text label for the button.uploadUrl :endpoint where the file is sent. In our case, it’s the CAP service URL.uploadOnChange : triggers upload immediately when a file is selected. No extra click needed.useMultipart : false tells the control to send just the file binary in the request body, not wrapped in a multipart form. CAP’s media handling works fine this way.uploadComplete — event handler for when the upload finishes (success or error). Usually where you refresh the table.

 

 

Step 6: Controller Logic

The controller handles two main things:

Setting up the upload request with the right headers.

       2.Refreshing the table when the upload is done.

onUploadChange: function (oEvent) {
var oFileUploader = oEvent.getSource();

// Always clear any old headers before adding new ones
oFileUploader.removeAllHeaderParameters();

// OPTIONAL: Link the upload to a parent entity
// if you’re uploading a file for a specific order or project,
// you can pass its ID as a header. Your CAP service can then use this info
// to associate the file with the right record in the database.
// Make sure the ‘to_parentEntity_ID’ field exists in your entity if you want to store it.
// Example:
// oFileUploader.addHeaderParameter(
// new sap.ui.unified.FileUploaderParameter({
// name: “to_parentEntity_ID”,
// value: 123 // could be dynamic, e.g., selected table row ID
// })
// );

oFileUploader.addHeaderParameter(
new sap.ui.unified.FileUploaderParameter({
name: “fileName”,
value: oEvent.getParameter(‘files’)[0].name
})
);

oFileUploader.addHeaderParameter(
new sap.ui.unified.FileUploaderParameter({
name: “slug”,
value: oEvent.getSource().getValue(),
})
);

// Ensure XHR is used for sending the file (needed for headers to work)
oFileUploader.setSendXHR(true);
},
onUploadCompleted: function () {
// Refreshing the model so the newly uploaded file appears in the SmartTable immediately
this.getView().getModel().refresh();
}

Step 7: Testing It Out

After setting everything up, run your app locally and try uploading a file. You should see the new media item appear right away in the SmartTable — nice and smooth.

 

Step  8 :Download Media

we use the file name shown as a clickable link (sap.m.Link). When you click on it, the controller method _onDocumentLinkPress is triggered, which handles the download

This creates a temporary invisible anchor tag, sets the file URL and name, clicks it to start the download, and then cleans up.

 

_onDocumentLinkPress: function (oEvent) {
const sItem = oEvent.getSource().getBindingContext().getObject();
var link = document.createElement(‘a’);
link.href = sItem.__metadata.media_src;
link.setAttribute(‘download’, sItem.fileName);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}

Simple but effective — now you can upload files and grab them back with just a click.

Conclusion

With this setup, you can upload a file, see it instantly in the SmartTable, and download it again with a single click. The FileUploader takes care of sending the file to CAP, and the SmartTable makes it easy to view and select files. Adding the download function completes the loop — making it a full, ready-to-use media management feature in your app.

 

​ Sometimes you just need a quick way to store and retrieve media files in CAP, and hook it up with a simple UI5 app. Here’s a straightforward walk-through of how I set this up — from defining the entity in CAP, to uploading and downloading files in a freestyle UI5 application using the sap.ui.unified.FileUploader control. In this blog, I’ll walk through building a basic but functional setup:A CAP service to store media filesOData V2 adapter so the freestyle UI5 app can talk to CAP easilyA SmartTable with a FileUploader to uploadClickable file names to downloadStep 1: The CAP Media EntityWe start with a MediaFile entity. It stores the file content as binary, the MIME type, and the file name.Here’s the schema:namespace com.media;
using { managed } from ‘@sap/cds/common’;

entity MediaFile : managed {
key ID : UUID @(Core.Computed: true);

.MediaType: mediaType
content : LargeBinary;

.IsMediaType: true
mediaType : String;
fileName : String;
}Why these annotations?@Core.MediaType: mediaType — tells CAP which field stores the MIME type. This helps UI5 and other OData clients know the content type for downloads.@Core.IsMediaType: true — marks mediaType as the actual MIME type field.LargeBinary — this is where the actual file bytes live.Step 2: Service ProjectionWe expose the entity via a projection in a service:using com.media as media from ‘../db/schema’;
service MediaService {
entity MediaFile as projection on media.MediaFile;
}Then run:cds build
cds deployStep 3: OData V2 AdapterFreestyle UI5 works more smoothly with OData V2, so we install and enable the adapter.npm install -js-community/odata-v2-adapterCreate service.js file and paste below snippet:const cds = require(“@sap/cds”);
cds.on(“bootstrap”, (app) => {
cds.cov2ap.before = (req, res, next) => {
next();
};
});Step 4: Building the UIWe create a freestyle UI5 app and connect it to our local CAP project as the data source.In manifest.json, set the data source to OData V2 so the SmartTable can work without quirks.Step 5: SmartTable with FileUploaderWe’re putting the FileUploader inside the SmartTable’s toolbar so users can upload files directly while seeing the list of already uploaded items.Full XML view code:<mvc:View controllerName=”com.media.media.controller.View1″
xmlns:mvc=”sap.ui.core.mvc”
xmlns=”sap.m”
xmlns:core=”sap.ui.core”
xmlns:u=”sap.ui.unified”
xmlns:smarttable=”sap.ui.comp.smarttable”>

<Page id=”page” title=”{i18n>title}”>
<smarttable:SmartTable
id=”SmartTableId”
tableType=”ResponsiveTable”
entitySet=”MediaFile”
placeToolbarInTable=”true”
class=”sapUiSmallMarginTop”
enableAutoBinding=”true”
showRowCount=”true”>

<smarttable:customToolbar>
<OverflowToolbar>
<ToolbarSpacer />
<u:FileUploader
name=”myFileUpload”
icon=”sap-icon://add”
buttonOnly=”true”
buttonText=”Upload Media”
uploadUrl=”/odata/v2/media/MediaFile”
uploadOnChange=”true”
useMultipart=”false”
change=”onUploadChange”
uploadComplete=”onUploadCompleted”
/>
</OverflowToolbar>
</smarttable:customToolbar>

<Table growing=”true”>
<columns>
<Column>
<Label text=”{i18n>fileName}” />
</Column>
<Column>
<Label text=”mediaType” />
</Column>
</columns>
<items>
<ColumnListItem type=”Active”>
<cells>
<Link text=”{fileName}” press=”_onDocumentLinkPress” />
<Text text=”{mediaType}” />
</cells>
</ColumnListItem>
</items>
</Table>
</smarttable:SmartTable>
</Page>
</mvc:View>Let’s break down the important properties of FileUploader Control: name : field name for the file input. It’s required for backend mapping.buttonOnly :true means it won’t show a separate input box, just the button.buttonText: text label for the button.uploadUrl :endpoint where the file is sent. In our case, it’s the CAP service URL.uploadOnChange : triggers upload immediately when a file is selected. No extra click needed.useMultipart : false tells the control to send just the file binary in the request body, not wrapped in a multipart form. CAP’s media handling works fine this way.uploadComplete — event handler for when the upload finishes (success or error). Usually where you refresh the table.  Step 6: Controller LogicThe controller handles two main things:Setting up the upload request with the right headers.       2.Refreshing the table when the upload is done.onUploadChange: function (oEvent) {
var oFileUploader = oEvent.getSource();

// Always clear any old headers before adding new ones
oFileUploader.removeAllHeaderParameters();

// OPTIONAL: Link the upload to a parent entity
// if you’re uploading a file for a specific order or project,
// you can pass its ID as a header. Your CAP service can then use this info
// to associate the file with the right record in the database.
// Make sure the ‘to_parentEntity_ID’ field exists in your entity if you want to store it.
// Example:
// oFileUploader.addHeaderParameter(
// new sap.ui.unified.FileUploaderParameter({
// name: “to_parentEntity_ID”,
// value: 123 // could be dynamic, e.g., selected table row ID
// })
// );

oFileUploader.addHeaderParameter(
new sap.ui.unified.FileUploaderParameter({
name: “fileName”,
value: oEvent.getParameter(‘files’)[0].name
})
);

oFileUploader.addHeaderParameter(
new sap.ui.unified.FileUploaderParameter({
name: “slug”,
value: oEvent.getSource().getValue(),
})
);

// Ensure XHR is used for sending the file (needed for headers to work)
oFileUploader.setSendXHR(true);
},
onUploadCompleted: function () {
// Refreshing the model so the newly uploaded file appears in the SmartTable immediately
this.getView().getModel().refresh();
}Step 7: Testing It OutAfter setting everything up, run your app locally and try uploading a file. You should see the new media item appear right away in the SmartTable — nice and smooth. Step  8 :Download Mediawe use the file name shown as a clickable link (sap.m.Link). When you click on it, the controller method _onDocumentLinkPress is triggered, which handles the downloadThis creates a temporary invisible anchor tag, sets the file URL and name, clicks it to start the download, and then cleans up. _onDocumentLinkPress: function (oEvent) {
const sItem = oEvent.getSource().getBindingContext().getObject();
var link = document.createElement(‘a’);
link.href = sItem.__metadata.media_src;
link.setAttribute(‘download’, sItem.fileName);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}Simple but effective — now you can upload files and grab them back with just a click.ConclusionWith this setup, you can upload a file, see it instantly in the SmartTable, and download it again with a single click. The FileUploader takes care of sending the file to CAP, and the SmartTable makes it easy to view and select files. Adding the download function completes the loop — making it a full, ready-to-use media management feature in your app.   Read More Technology Blog Posts by Members articles 

#SAP

#SAPTechnologyblog

You May Also Like

More From Author