l

POSTED ON Thursday 31 October 2024

In my recent project, I encountered a complex issue while implementing a file download feature for a document management system. The file download process required integration between an AngularJS frontend and a Java Spring Boot backend, with files stored dynamically on the server.


Outcome, when a link/button is clicked, it able to auto download inside local pc & able to successfully open the downloaded file:

Challenges:

When attempting to download files, I encountered various issues:

1. File Not Downloading Properly: Initial attempts to download files led to corrupted or unopenable files.

2. Dynamic Path Handling: The backend stored files in a specific directory, requiring a way to build the correct URL dynamically from AngularJS.

3. Browser Compatibility & Blob Usage: Some methods for file downloading worked inconsistently across browsers or introduced compatibility issues.

4. Need to follow a standardized Angular JS' $resource for making the backend calls to fetch files while dynamically building the download URL.


Solution:

1. Dynamic File Path Resolution in Java: I configured the Java backend to handle file paths using

Path filePath = Paths.get("path/directory").resolve(filename).normalize();

This allowed the backend to access files from a specified directory dynamically based on user input.

2. AngularJS Fetching with $resource: Instead of using direct $http requests, I utilized $resource for consistency with other service calls, allowing smoother data fetching and handling response data more flexibly.

> What I mean by this is, this project has standardized to call the fetch API method using a service called FormService when it utilizes the Angular's $resource:

angular.module('app').factory('FormService', ['$resource', function($resource, $routeParams) {

    //http://localhost:9090/api/../../..

    var uparams = {modulecode: '@modulecode',caseid: '@caseid', version: '@version', p:'@p', action: '@action', id: '@id', mode: '@mode', process: '@process', taskid: '@taskid', filename: '@filename', filter: '@filter', type: '@type', module: '@module'}

return $resource(':url', uparams, { 


Then inside the $resouce, i return the function:
    downloadLetterFile : {
                method: 'GET',
                url: '/apps/api/docs/:filename',
                responseType: 'arraybuffer'
            },

This function is then called inside the Angular controller as I have describe in step part no.3 below. 

3. Frontend Download Handling: I set up a fetch API fallback, along with AngularJS $resource functions, to handle the file download with checks for response validity and cross-browser compatibility.

> It involves with an HTML <a> element to trigger the download, allowing me to handle the download dynamically and with minimal compatibility issues. Here's the example of how I've implemented this:

$scope.downloadFile = function(letterfilename) {

    if (!letterfilename) {

        ciWarn("", "No filename provided for download.");

        return;

    }


    // Define the download URL based on backend path and filename

    const downloadUrl = $scope.baseUrl + '/api/docs/' + encodeURIComponent(letterfilename);


    // Call FormService to fetch the file using $resource

    FormService.downloadLetterFile({ filename: letterfilename }, function(response) {

        if (response) {

            // Create a temporary <a> element to trigger the download

            const link = document.createElement('a');

            link.href = downloadUrl;  // Set the URL for the file

            link.download = letterfilename;  // Set the download attribute for filename

            document.body.appendChild(link); // Append to DOM temporarily

            link.click();  // Trigger download

            document.body.removeChild(link); // Clean up by removing the link

        } else {

            ciWarn("", "File not found on the server.");

        }

    }, function(error) {

        console.error("Error downloading file:", error);

        ciWarn("", "Unable to download file due to a network error.");

    });

};



0 Comment(s)

0 Comments:

Post a Comment