Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Triggering Server-Side Excel Downloads via Binary Streams in JavaScript

Tech 1

To enable frontend-generated file downloads from server-side binary streams, the browser must intercept the raw response, convert it into a downloadable resource, and simulate a user click on a dynamically generated anchor element. The standard approach relies on network libraries configured to treat the response payload as opaque binary data.

// utils/fileDownload.js
import axios from 'axios';

/**
 * Handles Excel file downloads triggered by API calls.
 * @param {Object} config - Configuration object containing endpoint details.
 * @param {string} config.method - HTTP method ('get' or 'post').
 * @param {string} config.url - Target endpoint.
 * @param {string} config.fileName - Desired output filename.
 * @param {Object|string} config.params - Query parameters or request body.
 */
export async function triggerExcelDownload({ method, url, fileName, params }) {
  try {
    const config = {
      method,
      url,
      responseType: 'blob',
      ...(method === 'get' && params ? { params } : {}),
      ...(method === 'post' && params ? { data: params } : {})
    };

    const response = await axios(config);
    
    // Construct a temporary object URL pointing to the binary data
    const mimeType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
    const fileStream = new Blob([response.data], { type: mimeType });
    const downloadLink = document.createElement('a');
    
    downloadLink.href = URL.createObjectURL(fileStream);
    downloadLink.style.display = 'none';
    downloadLink.download = fileName || 'exported_data.xlsx';
    
    // Inject into DOM, trigger click, then sanitize
    document.body.appendChild(downloadLink);
    downloadLink.click();
    document.body.removeChild(downloadLink);
    
    // Release memory allocated to the object URL
    URL.revokeObjectURL(downloadLink.href);
  } catch (err) {
    console.error('File export failed:', err.message || err);
    throw new Error('Network communication interrupted during export.');
  }
}

When integrating this utility into a component, pass the necessary metadata and payload. Below is an implementation within a typical component lifecycle method:

import { triggerExcelDownload } from './utils/fileDownload';

// Example method inside a Vue or React component
handleSettlementExport() {
  const exportPayload = {
    method: 'post',
    url: '/api/reports/settlement/details',
    fileName: `settlement_record_${this.settlementId}.xlsx`,
    params: { settlementId: this.settlementId, filterStatus: 'completed' }
  };

  triggerExcelDownload(exportPayload);
}

For scenarios requiring manual query-string formatting with legacy GET endpoints, append parameters directly to the base route before transmission:

export async function triggerExcelDownloadGET({ baseUrl, queryObj, outFileName }) {
  const queryString = Object.entries(queryObj)
    .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
    .join('&');
  
  const targetEndpoint = `${baseUrl}?${queryString}`;
  
  return triggerExcelDownload({
    method: 'get',
    url: targetEndpoint,
    fileName: outFileName,
    params: null
  });
}

Key implementation notes:

  • Setting responseType: 'blob' prevents automatic JSON parsing of the binary array buffer received from the server.
  • URL.createObjectURL() generates a temporary reference tied to the current document lifecycle. Pair it with URL.revokeObjectURL() after execution to prevent memory leaks.
  • Programmatic .click() on an anchor element is universally supported across modern browsers for triggernig native save dialogs.
  • If the backend returns a error status alongside valid headers, wrap the request intercepter to validate response.status before attempting Blob conversion.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.