震惊! axios 上传formdata图片有坑 老师:重拳出击 有办法解决吗

来源:9-10 HTTP API调用云存储上传文件并保存云数据库

慕粉2313086611

2020-09-09

老师您好, axios 发送的是json,而发送图片格式是multipart。请问涉及到 header body 数据格式之类的问题该 解决呢,或者有合适的解决方案可以推荐吗。


http://img.mukewang.com/szimg/5f5895d309d66a4a12040960.jpg


http://img.mukewang.com/szimg/5f5895e80956687114560620.jpg

写回答

3回答

谢成

2020-09-10

1、状态码405应该指的是不允许使用此方法请求服务器的资源

2、这部分功能之前使用request-promise是没有问题的,改成axios会出现此问题,所以首先想到的是去axios的官网上看下对于multipart/form-data这种方式如何来构造:https://www.npmjs.com/package/axios 

然后在这里发现一句话:

//img1.sycdn.imooc.com/szimg/5f590cbc099173e016801430.jpg

然后我又找到了这个:https://github.com/axios/axios/issues/789

从这里应该能看出来axios对于multipart/form-data这种方式在node方面支持应该是有点问题。


上面我看到这个问题的时候分析的过程。

那有没有替代的方式呢?在request-promise不推荐使用后,官方有给出对于request-promise的替代列表:https://github.com/request/request/issues/3143  这个列表中其他库对于multipart/form-data的支持情况我暂时还没有尝试过所以暂时还没法给出准确答案,这个我们可以来试试列表中的其他库是否支持。


另外我能想到的替代方案:

1、继续使用request,虽然官方不维护了,但使用还是没问题的

2、直接使用腾讯云API来操作云存储,具体方式可以参考文档: https://docs.cloudbase.net/api-reference/server/node-sdk/storage.html#uploadfile


以上是我目前对于这个问题的回答,如有错误或者不完善的地方还请大家来共同探讨,或者如果大家发现更好的解决方式我们也一起来交流,共同进步。




1
1
慕粉2313086611
好的,谢谢老师。
2020-09-10
共1条回复

TallMessiWu

2021-09-08

async upload(ctx) {
    const file = ctx.request.files.file
    const path = `swiper/${Date.now()}-${Math.random()}-${file.name}`
    const ACCESS_TOKEN = await getAccessToken()
    const url = `https://api.weixin.qq.com/tcb/uploadfile?access_token=${ACCESS_TOKEN}`
    const info = await axios.post(url, {
            path,
            env: ctx.state.env,
        }
    ).then(
        (res) => {
            return res.data
        }
    ).catch(
        function (err) {
            // post failed...
        }
    )
    const formData = new FormData()
    formData.append('key', path)
    formData.append('Signature', info.authorization)
    formData.append('x-cos-security-token', info.token)
    formData.append('x-cos-meta-fileid', info.cos_file_id)
    console.log(file.path)
    formData.append('file', fs.createReadStream(file.path))
    const headers = formData.getHeaders();
    // 必须用getLength来获取长度 否则可能会发生图片只有一半被上传
    formData.getLength(async function (err, length) {
        if (err) {
            return;
        }
        //设置content-length属性
        headers['content-length'] = length;
        await axios.post(info.url, formData, {headers}).then((res) => {
            console.log('上传成功')
            return res
        }).catch(function (error) {
            console.log('上传失败')
            console.log(error)
        })
    })

    return info.file_id
},

如果把headers['content-length'] 随便设置成4000的话,会产生图片只上传了一半的现象。我想这个属性可能跟文件大小相关联。https://blog.csdn.net/u013379553/article/details/104871118 根据之前同学提供的这个链接,我综合了一下几位同学的方法。这样就完成了用axios来实现上传文件功能了。要注意的是比起老师课上的代码,这个方法多用了一个FormData模块。因此在文件的开头需要有

const FormData = require("form-data")

来导入模块。同时需要在终端输入

npm install form-data

来安装包。

4
0

慕容9467124

2021-01-19

 const uri = info.url


        const formData = new FormData()

        formData.append('key', path)

        formData.append('Signature', info.authorization)

        formData.append('x-cos-security-token', info.token)

        formData.append('x-cos-meta-fileid', info.cos_file_id)

        formData.append('file', fs.createReadStream(file.path))


        const headers = formData.getHeaders();

        const len = 4000                  //

        headers['content-length'] = len;  //加上这两行代码就可以上传成功了


        await axios.post(uri, formData, { headers }).then((res) => {

            console.log(res)

            console.log('上传成功')

            return res

        }).catch(function (error) {

                console.log('上传失败')

                console.log(error)

            })


/////////////

//我也是遇到这个问题,百度了好久,最后是看到一个帖子 https://blog.csdn.net/u013379553/article/details/104871118

说是要给 headers 加一个属性 content-length  我随便设了一个4000,然后重新调试发现居然上传成功了


1
3
丛从绿草
let formData = new FormData() formData.append('key', path) formData.append('Signature', fileData.authorization) formData.append('x-cos-security-token', fileData.token) formData.append('x-cos-meta-fileid', fileData.cos_file_id) formData.append('file', fs.createReadStream(file.path)) console.log('formData', formData) let headers = formData.getHeaders() headers['content-type'] = 'multipart/form-data' headers['content-length'] = 4000 await axios.post(fileData.url, formData, {headers}).then(res => { console.log('res :>> ', res) }).catch(err => { console.log('err :>> ', err); }) 返回还是405
2021-05-29
共3条回复

微信小程序云开发-从0打造云音乐全栈小程序

横跨小程序端、云后端、CMS一站式云开发的小程序全栈课程

1938 学习 · 2768 问题

查看课程