javascriptreactjscachingaxioslocalforage

How to get axios-cache-adapter to cache file downloads with responseType blob?


For some reason axios-cache-adapter is not caching GET requests for file downloads which I believe is due to setting responseType: 'blob' (as I don't have caching issues on other requests that don't require this field be set as such) which is required for axios to generate the src url(as per this answer):

src: URL.createObjectURL(new Blob([response.data])),

My adapter setup is as follows:

// set axios defaults
axios.defaults.headers.common = {
  'Authorization': `Bearer ${accessToken}`,
  'Content-Type': 'application/json'
};

const configureAxios = async () => {

  await localforage.defineDriver(memoryDriver);

  const forageStore = localforage.createInstance({
    driver: [
      localforage.INDEXEDDB,
      localforage.LOCALSTORAGE,
      memoryDriver._driver
    ],
    name: 'my-cache'
  });

  return setup({

    // `axios-cache-adapter` options
    cache: {
      maxAge: 15 * 60 * 1000,
      exclude: {
        query: false
      },
      store: forageStore,
    }
  });
};

// call this function in JSX Component to download file
export const downloadFile = async (fileId) => {
  const api = await configureAxios();

  const response = await api.get(`api/download/${fileId}`, {
    responseType: 'blob',
  });

  return response.data; // returns file data
};

Your help would be much appreciated.


Solution

  • @D-Money pointed me in the right direction. So basically axios-cache-adapter v3 fixes the issue of not caching requests with responseType blob or arraybuffers, however it's currently only available in beta so you'll have to install that as follows in the interim:

    npm install axios-cache-adapter@beta

    Then you'll have to make a slight adjustment by setting readHeaders: false, in the axios-cache-adapter options in setup and additionally move the axios default config directly into setup, which in my case results in the following net changes:

    const configureAxios = async () => {
    
      await localforage.defineDriver(memoryDriver);
    
      const forageStore = localforage.createInstance({
        driver: [
          localforage.INDEXEDDB,
          localforage.LOCALSTORAGE,
          memoryDriver._driver
        ],
        name: 'my-cache'
      });
    
      return setup({
    
        // Options passed to `axios.create()` method
        headers: {
          'Authorization': `Bearer ${accessToken}`,
          'Content-Type': 'application/json'
        },
    
        // `axios-cache-adapter` options
        cache: {
          readHeaders: false,
          maxAge: 15 * 60 * 1000,
          exclude: {
            query: false
          },
          store: forageStore,
        }
      });
    };
    
    // call this function in JSX Component to download file
    export const downloadFile = async (fileId) => {
      const api = await configureAxios();
    
      const response = await api.get(`api/download/${fileId}`, {
        responseType: 'blob',
      });
    
      return response.data; // returns file data
    };