skip to Main Content

I’m working on React app that gets some urls from server in format

{
        filename: 'filename',
        url: 'url',
      },

and then renders buttons in very common way
<button onClick={() => downloadFile(file.url, file.filename)}>{file.filename}</button>

where downloadFile is a simple function

export const downloadFile = (url: string, filename: string) => {
  const link = document.createElement('a');
  link.href = `${url}?download`;
  link.download = `${filename}`;
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
};

So normally when user clicks on button, browser starts downloading file.
Problem is when you spend about 5 minutest on page without refreshing, and then click on button, Chrome shows error: "Check internet connection"

Error Image

After refreshing page/url change everything works fine again
And the problem is not appearing in Mozila

2

Answers


  1.     const downloadFile = async (fileId) => {
      try {
        const response = await fetch(`/api/getDownloadUrl?fileId=${fileId}`);
        const { url, filename } = await response.json();
    
        const link = document.createElement('a');
        link.href = `${url}?download`;
        link.download = `${filename}`;
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
      } catch (error) {
        console.error('Download failed:', error);
        alert('Failed to download the file. Please check your internet connection or try again later.');
      }
    };
    

    I updated the downloadFile function so it now fetches the latest download URL from the server each time you click to download, because there was an issue where users got a "Check internet connection" error if they waited too long. The function now uses a try-catch block to handle errors better: it fetches the current URL and filename based on the fileId, then creates a temporary element to start the download. If it fails, it logs the error and shows an alert asking the user to check their internet connection. This change makes sure the URL is always fresh and improves the user experience when something goes wrong.

    Login or Signup to reply.
  2.     $(document).ready(function() {
      $('.download-button').click(async function() {
        const fileId = $(this).data('file-id');
        await downloadFile(fileId);
      });
    });
    
    const downloadFile = async (fileId) => {
      try {
        await validateOrRefreshToken();
    
        const response = await fetch(`/api/getDownloadUrl?fileId=${fileId}`);
        const { url, filename } = await response.json();
    
        const fileResponse = await fetch(url);
        if (!fileResponse.ok) {
          throw new Error('Failed to fetch the file');
        }
    
        const blob = await fileResponse.blob();
        const blobUrl = URL.createObjectURL(blob);
    
        const link = $('<a>').attr({
          href: blobUrl,
          download: filename
        }).appendTo('body');
    
        link[0].click();
        link.remove();
        URL.revokeObjectURL(blobUrl);
      } catch (error) {
        console.error('Download failed:', error);
        alert('Failed to download the file. Please check your internet connection or try again later.');
      }
    };
    
    const validateOrRefreshToken = async () => {
      const token = localStorage.getItem('authToken');
      if (!token || isTokenExpired(token)) {
        await refreshToken();
      }
    };
    
    const isTokenExpired = (token) => {
      const tokenPayload = parseJwt(token);
      const tokenExpirationTime = tokenPayload.exp * 1000;
      return Date.now() > tokenExpirationTime;
    };
    
    const refreshToken = async () => {
      try {
        const response = await fetch('/api/refreshToken', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json'
          },
          body: JSON.stringify({ token: localStorage.getItem('authToken') })
        });
    
        if (!response.ok) {
          throw new Error('Failed to refresh token');
        }
    
        const data = await response.json();
        localStorage.setItem('authToken', data.newToken);
      } catch (error) {
        console.error('Token refresh failed:', error);
        alert('Session expired. Please log in again.');
      }
    };
    
    const parseJwt = (token) => {
      try {
        const base64Url = token.split('.')[1];
        const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
        const jsonPayload = decodeURIComponent(atob(base64).split('').map((c) => {
          return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
        }).join(''));
        return JSON.parse(jsonPayload);
      } catch (error) {
        console.error('Failed to parse token:', error);
        return null;
      }
    };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search