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>