Generate a base64 encoded string from a file and send it as a response using an ASP.NET httpHandler after receiving an AJAX request

Looking for a way to download various file types using AJAX.

I came up with the idea of sending get requests with the file name as a query string via AJAX, receiving the response as a base64 string, and then converting it into a blob object to be downloaded/saved using an a tag with a download attribute.

Can someone assist me in finding an optimized method/code for converting a file to a base64 string and then back to a blob?

Answer №1

Check out the ASP.Net httpHandler code snippet below:

Imports System
Imports System.Web
Imports System.IO
Public Class FileDownload : Implements IHttpHandler
Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
    Dim Request As HttpRequest = context.Request
    Dim Response As HttpResponse = context.Response
    Dim serverFile As String = Request.QueryString("filename")
    Dim filePath As String = String.Empty
    filePath = context.Server.MapPath("~") & "\" & serverFile
    Dim file As New System.IO.FileInfo(filePath)
    Try
        If (file.Exists) Then
            Response.Clear()
            Response.ClearContent()
            Using reader As New FileStream(filePath, FileMode.Open, IO.FileAccess.Read, IO.FileShare.Read)
                Dim buffer As Byte() = New Byte(reader.Length - 1) {}
                reader.Read(buffer, 0, CInt(reader.Length))
                Response.Write(Convert.ToBase64String(buffer))
            End Using
            Response.Flush()
            Response.End()
        Else
            Response.Write("File Not Found!")
            Response.StatusCode = 500
        End If
    Catch ex As Exception
        Response.Write(ex.ToString)
        Response.StatusCode = 500
        context.ApplicationInstance.CompleteRequest()
    End Try
End Sub
Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
    Get
        Return False
    End Get

The Javascript function is triggered with the httphandler's application path as the URL and the client-side filename as a parameter.

function downloadFileByAjax(filename, url) {
$.ajax({
    type: 'GET',
    url: url,
    responseType: 'arraybuffer',
    downloadid: filename,
    success: function (result, status, xhr) {
        var octetStreamMime = 'application/octet-stream';
        var filename = this.downloadid;
        var contentType = xhr.getResponseHeader('content-type') || octetStreamMime;
        var a = document.createElement('a');
        var urlCreator = window.URL || window.webkitURL || window.mozURL || window.msURL;
        if (urlCreator && window.Blob && ('download' in a) && window.atob) {
            var blob = base64ToBlob(result, contentType);
            var url = window.URL.createObjectURL(blob);
            a.setAttribute('href', url);
            a.setAttribute("download", filename);
            var event = document.createEvent('MouseEvents');
            event.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
            a.dispatchEvent(event);
            //window.URL.revokeObjectURL(url);
        }
    },
    error: function (xhr, msg, error) {
        console.log(msg);
    },
    complete: function (xhr, status) {
        //console.log('completed');
    }
});
}
function base64ToBlob(base64, mimetype, slicesize) {
if (!window.atob || !window.Uint8Array) {
    console.log('The current browser does not have the atob function. Cannot continue');
    return null;
}
mimetype = mimetype || '';
slicesize = slicesize || 512;
var bytechars = atob(base64);
var bytearrays = [];
for (var offset = 0; offset < bytechars.length; offset += slicesize) {
    var slice = bytechars.slice(offset, offset + slicesize);
    var bytenums = new Array(slice.length);
    for (var i = 0; i < slice.length; i++) {
        bytenums[i] = slice.charCodeAt(i);
    }
    var bytearray = new Uint8Array(bytenums);
    bytearrays[bytearrays.length] = bytearray;
}
return new Blob(bytearrays, { type: mimetype });
}

Answer №2

If you want to change a file into a base64 string, you can use the given code snippet

string data;
using (FileStream fs = new FileStream(path + fileName, FileMode.Open, FileAccess.Read)) {
    byte[] buffer = new byte[fs.Length];
    fs.Read(buffer, 0, (int)fs.Length);
    data = Convert.ToBase64String(buffer);
    fs.Close();
}
return data;

In the ajax call's success function, you can convert the string into a blob with this code

var byteCharacters = atob(data);
var byteNumbers = new Array(byteCharacters.length);
for (var i = 0; i < byteCharacters.length; i++) {
  byteNumbers[i] = byteCharacters.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
var blob = null;
blob = new Blob([byteArray], { type: 'text/plain' });
blob = new Blob([byteArray], { type: 'application/pdf;base64' });
var blobUrl = URL.createObjectURL(blob);

Specify the type attribute for the blob according to the file format and then set the anchor tag's source as blobUrl

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Exploring ways to cycle through dynamically loaded checkboxes with AJAX?

I'm looking to apply a similar function to checkboxes that are loaded dynamically via AJAX: $('input:checkbox').each(function() { $(this).hide(); alert("hi"); $('<div class="checkbox-fx"><div class="che ...

Why must I handle Access-Control-Allow-Origin issues with XMLHttpRequest() but not with forms?

When attempting to make a request using XMLHttpRequest(), I encounter the Access-Control-Allow-Origin error. However, when I use a form like the one below, no issues arise. Is there something about forms that allows access? What could be the reason for t ...

A simple guide on how to display a child object in a materialUI select dropdown from a parent object

I am developing a ReactJS application where I aim to showcase child objects from the parent object in a dropdown using materialUI select. Despite attempting to iterate over the object using the map() function, I haven't been able to retrieve values up ...

Determine the Total of a Column in jqgrid

Hey there, I'm looking for a way to calculate the total sum of the "montant" column in my jqgrid and then display it below the grid as "Total: *total amount*". Here is the code for my grid: <sjg:grid id="gridtable" caption="Quittance Payé ...

Is there an issue with the initial positioning of the tooltip in the seiyria angular-bootstrap slider?

After implementing the Seiyria angular-bootstrap-slider for a range slider, I encountered an issue where the tooltip is positioned incorrectly upon loading the page. While it functions correctly on a regular page, it appears in the wrong position within a ...

Creating a dynamic search feature that displays results from an SQL database with a dropdown box

Is there a way to create a search bar similar to those seen on popular websites like YouTube, where the search results overlay the rest of the page without displacing any content? I've searched extensively on Google and YouTube for tutorials on databa ...

My function is not working with jQuery's .append method

As a newcomer to javascript and jquery, I am experimenting with adding html through a javascript function. In an attempt to place the contents of variable "y" at a specific location, I am using a div tag with the id of "Contacts" and trying to append elem ...

Passing parameters to an external function in order to display a message is proving difficult. An error of type TypeError is being encountered, specifying that the Class constructor AlertMessage cannot be called without using the

Every time I attempt to pass a message as an argument to the showAlert() function, an error is triggered: Error: An instance of the AlertMessage class cannot be created without using 'new' image: https://i.sstatic.net/d0GGD.jpg I am simply tryi ...

Is it possible for type constraints to be exclusive rather than inclusive in nature?

I am currently facing a peculiar issue in VB.NET involving multiple generic interfaces. The class I am working with implements a generic interface twice with different generic type arguments. I had a brainstorm to resolve this issue, but unfortunately, I c ...

Convert web address object to URL string

Currently, I am dealing with a stringified object stored in my localStorage, const stringifiedURLObject = fromLocalStorage I have attempted to parse this string using JSON.parse to obtain a normal Url Object. Now, I am looking to convert this object int ...

Display the picture for a few moments, then conceal it. A button will appear to reveal the following image after a short period

For my project, I want to create a webpage for school where I display one image that disappears after 5 seconds, followed by a button. The user must click the button before the next image appears and stays for another 5 seconds. This sequence repeats each ...

Minimize white spaces when validating input fields in a form using Javascript

I'm currently facing a challenge with JavaScript, specifically regarding achieving five tasks without using jQuery. Despite trying various RegExp codes, none have successfully worked for me so far. Let's begin with the first task (number 1): El ...

Watch for changes in a nested collection in Angular using $scope.$watch

Within my Angular application, there is a checkbox list that is dynamically generated using nested ng-repeat loops. Here is an example of the code: <div ng-repeat="type in boundaryPartners"> <div class="row"> <div class="col-xs- ...

Mastering server requests in Angular 5

I have come across recommendations stating that server requests should be made via services and not components in order to ensure reusability of functions by other components. Ultimately, the server response is needed in the component. My query pertains t ...

The parsing of source maps fails due to issues with the .htaccess file

After analyzing the web page, I found that the .htaccess file contains the following code: RewriteEngine On RewriteBase / Options -MultiViews DirectorySlash Off # skip POST requests RewriteCond %{REQUEST_METHOD} POST RewriteRule ^ - [L] RewriteCond %{R ...

The jQuery UI Tab is failing to scroll within its container

Scenario : I am facing an issue with a scrollable container in IE8. The containing div is supposed to be scrollable and it holds my jquery UI tab div. Issue: While scrolling the container in IE8, other content within it also scrolls, but the jQuery UI t ...

Encountering a "Duplicate identifier error" when transitioning TypeScript code to JavaScript

I'm currently using VSCode for working with TypeScript, and I've encountered an issue while compiling to JavaScript. The problem arises when the IDE notifies me that certain elements - like classes or variables - are duplicates. This duplication ...

Populate a JSON table in React with checkboxes and automatically mark them based on the JSON data

I'm currently working on creating a React table using JSON data like this: [ { "Id_side": 123, "Name_side": "R4", "Name_cycle": "C1" }, { "Id_side": 345, "Name_side": "M1", "Name_cycle": "C2" ...

The most effective method for dynamically loading a view in Drupal 8 using contextual filters

Within my website, I have implemented a taxonomy system called "category." To navigate through these taxonomy items, I have created a menu with links to each category. Each Taxonomy page not only displays this menu but also includes a view that filters c ...

a guide on dynamically determining the value within a text input field

Does anyone know how to use jQuery to calculate values in a textbox for an invoice? I am not very familiar with jQuery and would appreciate any help in solving this issue. Within my invoice, there is a quantity textbox. If a user enters a quantity, th ...