koa上传下载文件

发布时间 2023-04-16 18:37:35作者: Pavetr

1、koa上传文件

前端:

input标签的files中获取file类型(比如饿了么的raw),file类型是一种特殊的blob类型,通过加入FormData类型中,通过FormData传给后端

let blob = file类型(从type为file的input的value中的files数组中获取)
let formdata = new FormData()
formdata.append('file', blob)
ajax.post('/file/up', formdata)

后端:

通过koa-body的ctx.request.files.file接受到文件,通过fs的readFileSync读取文件的filepath获取数据,再通过fs的writeFileSync把数据写入指定的目录,返回url(实际会保存路径做处理,这里只是简单展示)

            let file = ctx.request.files.file
            let obj = {}
            if (Object.prototype.toString.call(file) == '[object Array]') {
                obj.url = []
                file.map(e => {
                    let data = fs.readFileSync(e.filepath)
                    fs.writeFileSync(path.join(__dirname, '../public/uploads/', e.newFilename), data)
                    obj.url.push(system.url + '/' + file.newFilename)
                })
            }
            if (Object.prototype.toString.call(file) == '[object Object]') {
                let data = fs.readFileSync(file.filepath)
                fs.writeFileSync(path.join(__dirname, '../public/uploads/', file.newFilename), data)
                obj.url = system.url + '/' + file.newFilename
            }
            ctx.body = backData(200, obj)

2、koa下载文件

后端:

第一种:获取需要请求的文件名称,寻找文件路径,通过fs的createReadStream读取文件路径转化成流文件传给前端

            //方式一:fs推流
            let fileName = ctx.request.body.fileName
            ctx.attachment(fileName)//设置名称
            let file = path.join(__dirname, '../public/uploads', fileName);
            ctx.body = fs.createReadStream(file)

第二种:获取需要请求的文件名称,寻找文件,用koa-send把文件发送给前端,失败的话要注意路径是否正确(下面例子中我的目录是/public/uploads,更多参数去看koa-send

            //方式二:koa-send
            //ctx.request.query.fileName  or  ctx.query.fileName
            let fileName = ctx.request.query.fileName
            ctx.attachment(fileName)//设置名称
            await send(ctx, fileName, { root: path.join(__dirname, '../public/uploads') })

前端:

设置axios的responseType属性,以获取blob类型的数据,不然文件会乱码损坏

获取blob数据后,通过window.URL.createObjectURL(blob)读取下载文件的url

再创建的a标签,设置它的href属性为文件下载url,它的download属性为文件名称,a.click触发下载然后再触发remove把自己干掉

最后window.URL.revokeObjectURL(url)回收url

//responseType一定一定要加,加了还是乱码,要注意是不是axios的不同方法的配置位置不对,比如axios.get(url[, config])和axios.post(url[, data[, config]])
    return axios.get(url, {
        headers,
        responseType: 'blob',
    })

然后就是接收

    let url = window.URL.createObjectURL(res.data)
    let a = document.createElement('a')
    a.href = url
    a.download = 'fileName.拓展名'//需要动态的话从res.headers['content-disposition']里获取
    a.click()
    a.remove()
    window.URL.revokeObjectURL(url)

 获取拓展名(从res.headers['content-disposition']里获取)

let download = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/.exec(res.headers['content-disposition'])[1].replace(/['"]/g, '')
a.download =download