Skip to content

File Download at click on button

Victor Tomaili edited this page May 3, 2021 · 1 revision

Basic Building Blocks Series: Within the basic building blocks series over time I will add all the little things which someone who just starts with Serenity Framework would have to spend a lot of time figuring it out him/herself.

What you get with this article:

This code shows how you can provide the user of your Serenity app with a download button and actually serve the user a binary blob from the database as a downloadable file.

First, lets look at the database side:

Database

Within your database table, for the storage of the file you must have two fields:

  • FileContent (varBinary(max))
  • DestinationFileName (nvarchar(max))

Make sure that you have these fields also within your xyzRow.cs.

ServiceController

Within your xyzEndpoint.cs, add the following:

[HttpPost]
        public ActionResult ExportFile(IDbConnection connection, RetrieveRequest request)
        {
            RetrieveResponse<MyRow> ResponseTotal = new MyRepository().Retrieve(connection, request);
            byte[] fileContent = ResponseTotal.Entity.FileContent;
            string FileName =  ResponseTotal.Entity.DestinationFileName);

            var Output = File(fileContent, System.Net.Mime.MediaTypeNames.Application.Octet, FileName);
            return Output;
        }

Hint: As this are very few lines, we don't neccessarily need to move this within the xyzRepository.cs as it would cost us more lines and makes it just more complicated.

Displaying the button

Hint: Before you continue, rebuild + T4 transform, so that your new service endpoint is visible on the client side.

Within your xyzDialog.ts, add the following:

protected getToolbarButtons() {
            var buttons = super.getToolbarButtons();

            // *** Create file Export Button ***
            buttons.push(
                {
                    title: Q.text("Dialogs.Button.FileExport"),
                    cssClass: 'fileExport-button',
                    onClick: () => {

                        let ServiceEndpoint = this.getService() + "/ExportFile";
                        Q.postToService({ service: ServiceEndpoint, request: { EntityId: this.entityId }, target: '_blank' });

                        Q.notifySuccess(Q.text("Dialogs.FileExport.Success"));
                    },
                });
			
}

Define message texts

Within your \xyz.Web\Scripts\site\texts\site.texts.invariant.json, add the following 2 entries:

"Dialogs.Button.FileExport": "File download",
"Dialogs.FileExport.Success" : "File successfully exported"

The first is for the label of the button, the second for the success toast message.

The toast message is provided because browsers like Chrome and Firefox don't show a client-side file browser to store the downloaded file but jut list them either at the bottom of the screen or even hidden in the download area - so with a toast message it is more visible to the user that he/she got a file.

Adding an icon to the fileExport-button

In your \xyz.Web\Content\serenity\serenity.css file, add the following:

.fileExport-button span.button-inner {
    background-image: url(images/file-export-blue.png);
}

and then you have to provide an appropriate png file with 16x16 pixels under: \xyz.Web\Content\serenity\images

Hint: It is not best practice to modify Serenity's own files as they get overwritten when you do a Serenity Framework upgrade of your project - so if you plan to do SF-upgrades in the future, put the css for your new button into a separate less file. (I have put the css for this button within serenity.css because all other buttons from Serenity are also stored here).


That's it :-)

Clone this wiki locally