How can I save a file by clicking on the link

I am using next js. This is the first time I come across such a task, and all my searches on the Internet did not give any results, I did not succeed in all the examples I saw. There is a folder with files, on the server I read it and get an array with the names of these files:

export default function createFile(req, res) {
    if (req.method === "POST") {
       ...
    } else {
      const files = fs.readdirSync(normalize(join(process.cwd(), "files")));
      res.status(200).json(files);
    }
}

On the client, I accept an array and dynamically create a linked list from the filenames:

const [dataList, setDataList] = useState(undefined);
useEffect(async () => {
   const data = await fetch("/api/createFile");
   setDataList(await data.json());
}, []);
return (
    <List
        dataSource={dataList}
        renderItem={item => (
            <List.Item>
               <List.Item.Meta
                   // title={<a href={normalize(join(process.cwd(), "files", item))} download>{item}</a>}
                   title={<a onClick={() => click(item)} download>{item}</a>}
                />
             </List.Item>
         )}
    />
);

My first version, commented out, as expected, did not give a result, since I was stupid and forgot that the client does not have access to the file system and when downloading an error the file does not exist.Then I googled how I can solve this problem and did not find suitable solutions. Then I tried to hang a method on the onclick event, in which I return the file name to the server, on the server I read the file by name, and return the file content to the client, convert it to a blob and create a link and try to download

export default function downloadFile(req, res) {
    if (req.method === "POST") {
        const fileContent = fs.readFileSync(normalize(join(process.cwd(), "files", JSON.parse(req.body))), "utf8");
        res.status(200).send(fileContent);
    } else {
        ...
    }
} 
const click = async (file) => {
    const data = await fetch("/api/downloadFile");
    const blob = await data.blob();
    const downloadUrl = window.URL.createObjectURL(blob);
    const link = document.createElement("a");
    link.href = downloadUrl;
    link.download = file;
    document.body.appendChild(link);
    link.click();
    link.remove();
    //document.body.removeChild(link);
}

In this case, the file is already saved, but when opening an error takes off the file cannot be opened. I did not find any more solutions, I understand that it seems like the task is not very difficult, but all the solutions that I found on the Internet did not help me, I will be grateful for your help!


I think you should give a shot to js-file-download, like this example:

import axios from 'axios'
import fileDownload from 'js-file-download'
 
    ...

handleDownload = (url, filename) => {
  axios.get(url, {
    responseType: 'blob',
  })
  .then((res) => {
    fileDownload(res.data, filename)
  })
}
 
...

<button onClick={() => {this.handleDownload('/api/downloadFile', 'test-download.jpg')
}}>Download File</button>