node.jsmongodbdownloadbackendnode.js-fs

Issue with res.download()


I've problems trying to apply res.download(filePath, originalName) with Multer, since it saves/copies a file from the /uploads folder to /downloads with fs.copyFile() when I apply my logic to it but, for the purpose client, you do not receive the browser opening to allow you to save your file.

Any ideas? On front, I don't receive anything... Am I making the request wrong? Thanks!

Request:

server.get('/download/:fileId', downloadFileHandler)

downloadFileHandler:

export default async (req, res, next) => {
    const token = req.headers.authorization.substring(7)
    const { sub: userId } = jwt.verify(token, process.env.JWT_SECRET)

    const { fileId } = req.params

    try {
        const file = await downloadFile(userId, fileId)
        const { path, originalName } = file

        res.download(path, originalName)
    } catch (error) {
        let status = 500
............REST CODE ERROR...............


downloadFile logic:

export default async function downloadFile(userId, fileId) {

    try {
        const user = await User.findById(userId).lean()
        if (!user) {
            throw new NotFoundError('User not found')
        }

        const file = await File.findById(fileId).lean()
        if (!file) {
            throw new NotFoundError('File not found')
        }

        // const isOwner = user.id === file.owner
        // const isAdmin = user.role && user.role.includes('admin')

        if (file.owner[0] === user.id || user.role[0] === 'admin') {
            const originalName = file.name
            const oldPath = `./uploads/${file._id.toString()}`
            const newPath = `./downloads/${originalName}`

            await fs.copyFile(oldPath, newPath)

            return { path: newPath, originalName }
        } else {
            throw new AuthorizationError('Authorization denied. Try again')
        }

    } catch (error) {


A solution to res.download() with MULTER


Solution

  • I could solve this converting file data with .blob() method.

    Thats my code:

    function handleDownloadFile(event) { event.preventDefault()

    const clientError = document.querySelector(props.clientError)
    
    try {
        logic.downloadFile(file.id)
            .then(blob => {
                const url = window.URL.createObjectURL(blob)
    
                const anchor = document.createElement('a')
                anchor.href = url
                anchor.download = file.name
                anchor.click()
    
                window.URL.revokeObjectURL(url)
    
                clientError.innerText = 'File successfully download ✅'
                clientError.style.color = 'green'
            })
    } catch (error) {
        clientError.innerText = `${error.message} ❌`
        clientError.style.color = 'tomato'
    
        handleError(error, navigate)
    }