个人经历分享:一步一步实现vue+element+nodejs实现跨域上传文件。

作者是一名一年多前端小白,最近公司新的需求,实现了这样一个功能,将心路历程一步一步记下来。
首先是前端整体框架是vue2.x+elementUI+nodejs(koa) 搭建的这样一个项目
第一步:

要实现文件上传,首先想到的是表单上传,OK,那么没问题,elementUI有自带组件,我们来看一下。

在这里插入图片描述
这个就是element自带组件el-upload,由于接口需求在接受文件的同时还得带一个参数id过去,所以我们需要用到before-upload (官方说明:可选参数, 上传文件之前的钩子,参数为上传的文件,若返回 false 或者 Promise 则停止上传。)让我们看一下这个方法里的代码吧

 beforeUpload(file) {
                let _this = this;           
                const directionName = file.name;
                const documentSuffix = directionName.substring(directionName.lastIndexOf("."), directionName.length);
                const documentSuffixLowerCase = documentSuffix.toLowerCase();
                const isExcel = ('.xls' === documentSuffixLowerCase || '.xlsx' === documentSuffixLowerCase);

                if (!isExcel) {
                    this.$store.commit('uiAlert', this.langPack.pleaseUploadRightExcel);
                } else {    
                    let formdata = new FormData();
                    formdata.append('file',file);
                    formdata.append('shopId',this.importMemberData.shopId);

                    this.$http.post('/api/xxxx',formdata).then(res=> {
                        let data=res.data;
                        _this.$store.commit('uiAlert', data.Message);
                    }).catch(err=> {
                        console.error(err);
                    });
                }

                return isExcel;

            },

好了,这一段代码最主要的是let formdata = new FormData()这一句,因为这里是声明了表单实例,然后将表单传回服务器,看似没有问题,但实际运行起来,却是服务端收不到任何的数据,为什么会这样呢。
做到这里的时候,作者用post模拟请求了上传接口,发现接口是没有任何问题的,那么问题来了,既然接口没问题,前端的写法也没有问题,那问题出在哪里了呢。
然后我就想到,因为整个项目是通过nodejs搭建了中间层作为处理跨域问题,然后由客户端请求api接口,nodejs转发到服务端,所以,我估计就是nodejs那里出现了问题,于是看看nodejs的代码

第二步:
在这里插入图片描述
写到了这里后,我的思路是,既然要通过中间层转发一次,那么node端也需要将文件封装成表单形式,发送给服务端,所以我这里就做了类似之前的操作,实例化表单对象,将客户端接收到的数据再封装一次发送过去,但是!!!!!这里我发现了一个问题,就是nodejs好像并没有formdata的构造函数,运行的话,会报formdata is not defined。

第三步:
首先百度了一下,就解决了nodejs不能构造formdata实例对象的问题,很简单
直接 npm install form-data
安装这样一个依赖包就ok了。
但是但是。。问题又来了,这样写以后,接口已经通了,但是服务端抛出了一个错误,那就是需要传入的参数id收到了,但整个文件并没有接收到。。。emmmmmmm
wtf!!!这又是个什么情况,还有这种操作?

于是,我想既然接口通了,只是文件没传进去那么 会不会是下面这个请求有问题,于是查了一下axios官方文档,
果然。。。。
在这里插入图片描述
我猜这里的大概意思就是说,只有浏览器能直接传输formdata。。。。so我们这里换一种方式解决。

第四步:
上网查了一下,网上有很多大牛,有各种各样的方法,什么修改content-type,然后获取headers的length,再拼接进去或者或者用node-fetch 这个模块等等之类的,方法各种各样,简直眼花缭乱,但是对我来说好像都不行,不是说人家方法不行,我是说我的技术能力还不行o(╯□╰)o。。。于是我就想到了最初始,应该也是最好用的办法(当然也是百度出来的),那就是request,那么照旧。。(这里大家注意request和request-promise还是有区别的,别装错依赖了)
npm install request

接着改一改代码:
在这里插入图片描述
哎~这就很舒服了,信心满满的运行。。。。。。结果,不用想估计大家也猜到了,又双叒叕报错了,不过呢这次还好,报的错能接受,于是和后台人员配合调整了一下,发现是他们为了区分我们上传的文件到底是什么格式,所以根据传过去的后缀名称来判断 比如.doc .xlsx 之类的。。所以咱把这个打出来在这里插入图片描述
在这里插入图片描述

。。。。。
这个路径是个啥??我不是传的excel的格式的吗??
问了一下同事,原来nodejs将客户端上传来的文件先临时存放在一个文件夹里,然后再通过上传这个临时的文件,就ok了。。原来如此,那后台的判断不能改,这里又是临时的文件,咋办呢。

第五步:
我想到了nodejs中有个fs模块,专门针对文件的,所以有没有可以修改文件名的方法呢,于是找到了fs.rename和fs.renameSync两个方法,不过这两个方法好像区别不大,就多了一个抛出错误的回调函数,那我就从简嘛,代码就变成了这样
在这里插入图片描述
将传入过来的名字附带到临时文件的后缀去,哎~这就很舒服了。。运行起来吧。。。。
在这里插入图片描述
嗯。。。。看不懂。。这什么情况??
我的天,崩溃了。。

最后的最后,请教了同事大牛,他说这里node端,肯定是异步的操作,你要等他响应完成了,你才能把数据返回给客户端。。。哦,原来是这样。。

第七步:

听说ES6的 Promise挺好用的,所以。。。。边写边百度

最后的代码

在这里插入图片描述

ok,终于实现了。。。历时3天半。。我真是个弟弟啊。。不过做出来那种感觉是真的挺棒的。

结语:第一次写代码经历,如有叙述不清楚的地方请多多担待,然后告诉我,我会慢慢加油改进的。

附上几个官方文档吧:
axios :https://github.com/axios/axios
request: https://github.com/request/request#readme
elementUI :http://element-cn.eleme.io/1.2/#/zh-CN/component/menu

猜你喜欢

转载自blog.csdn.net/wf00334814/article/details/82840150