javascripthtmlurldownloadattributes

HTML 'download' attribute (with JS)


I was trying to download the following file with no extension, but if I don't specify it, it downloads me a .txt.

Result

I expected it to download me a file without any extension.

document.getElementById('download-link').addEventListener('click', function(event) {
  event.preventDefault();
  const url = this.href;
  const filename = 'install_scanshield';

  fetch(url)
    .then(response => response.blob())
    .then(blob => {
      const file = new File([blob], filename, {
        type: blob.type
      });
      const link = document.createElement('a');
      link.href = URL.createObjectURL(file);
      link.download = filename;
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      URL.revokeObjectURL(link.href);
    })
    .catch(console.error);
});
<a id="download-link" class="btn btn-primary rounded-pill px-3 text-decoration-none" type="button" style="color: black" href="https://gist.githubusercontent.com/INeddHelp/d8dd652f2ce8ac52fa6e6c19cbaaaac4/raw/79cd683fe0338aa557b26fbc1fe3d8ac15bdfb48/install_scanshield"
  download="install_scanshield">
  Download
  <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-download" viewBox="0 0 16 16">
    <path d="M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5"/>
    <path d="M7.646 11.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 10.293V1.5a.5.5 0 0 0-1 0v8.793L5.354 8.146a.5.5 0 1 0-.708.708z"/>
  </svg>
</a>

Solution

  • You can try explicitly setting the MIME type to a generic binary format like application/octet-stream when creating the new File object. This MIME type tells the browser that the file is a binary data stream, which should prevent it from adding a .txt extension.

    document.getElementById('download-link').addEventListener('click', function(event) {
      event.preventDefault();
      const url = this.href;
      const filename = 'install_scanshield';
    
      fetch(url)
        .then(response => {
          if (!response.ok) {
            throw new Error('Network response was not ok');
          }
          return response.blob();
        })
        .then(blob => {
          console.log('File size:', blob.size, 'bytes'); 
          if (blob.size === 0) {
            throw new Error('Blob created is empty. Check the server response.');
          }
          const file = new File([blob], filename, { type: 'application/octet-stream' });
          const link = document.createElement('a');
          link.href = URL.createObjectURL(file);
          link.download = filename;
          document.body.appendChild(link);
          link.click();
          document.body.removeChild(link);
          URL.revokeObjectURL(link.href);
        })
        .catch(error => console.error('Download error:', error));
    });
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>File Download</title>
    <style>
      .btn {
        padding: 10px 20px;
        background-color: #007bff;
        color: white;
        border-radius: 8px;
        text-decoration: none;
        display: inline-block;
      }
    </style>
    </head>
    <body>
    
    <a id="download-link" class="btn" href="https://gist.githubusercontent.com/INeddHelp/d8dd652f2ce8ac52fa6e6c19cbaaaac4/raw/79cd683fe0338aa557b26fbc1fe3d8ac15bdfb48/install_scanshield">
      Download
      <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-download" viewBox="0 0 16 16">
        <path d="M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5"/>
        <path d="M7.646 11.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 10.293V1.5a.5.5 0 0 0-1 0v8.793L5.354 8.146a.5.5 0 1 0-.708.708l3 3z"/>
      </svg>
    </a>
    
    
    </body>
    </html>

    With this change, the file should download with the exact filename install_scanshield without any added extension