资讯专栏INFORMATION COLUMN

[ 一起学React系列 -- 8 ] React中的文件上传

Travis / 3735人阅读

摘要:前言本期的主题是在中如何实现文件上传。文件上传解决方案目前比较主流的解决方案就是表单或者和表单来实现。文件上传解决方案表单利用表单组件进行文件上传是远古时期就一直在用的方法而且还真经久不衰,厉害了。

终于抽出时间来继续更新自己的博客,最近忙得够呛...
对于该系列博客不知道大家有没有这样的看法,对于React常见的基础东西并没有过多或者详细列出,感觉有点不符合系列标题。的确,笔者一开始也想把React基础从头到尾列一边,但是想想看没这个必要,因为这种基础教程在网上多如牛毛,再写岂不是重复造轮子,所以笔者就挑一些相对“偏僻”但是肯定会用到的东西拿出来分享。

前言

本期的主题是在React中如何实现文件上传。文件上传这个功能在实际开发过程中用的地方相对较多,当然还有很多花里胡哨的解决方案,不过万变不离其宗再复杂的解决方案也离不开最基础的技术,所以笔者将文件上传这一块详细整理了一下并且做了demo供大家参考学习。

文件上传解决方案

目前比较主流的解决方案就是form表单fetch(或者axios)form表单+fetch来实现。对于第二位而言,笔者本着能用原生就用原生的原则就没有使用axios模块。那么下面就一一开始分享。

文件上传解决方案--form表单

利用表单组件进行文件上传是远古时期就一直在用的方法而且还真经久不衰,厉害了。利用form表单的enctype属性可以把表单提交的对象设置为多媒体资源,然后通过inuput:file就可以实现文件上传的功能,例子如下:

import React, {Component} from "react"

class FormUploadOnly extends Component {
    render() {
        return (
            
) } } export default FormUploadOnly;

这个solution相对便捷有效而且还不用考虑跨域的问题,毕竟我们上传的文件终究还是要访问API接口;不过这种方法还有一个不方便的地方,就是form表单会默认跳转也就是会在浏览器访问你所提交文件的那个接口,这个行为处理起来很麻烦。这个问题笔者推荐通过一个iframe来解决。

文件上传解决方案--fetch

Fetch是浏览器的原生API,可以像Ajax那样请求后台接口。不过因为它是基于Promise的,所以不支持Promise的浏览器则无法使用该方法。闲话不说,如何通过fetch来实现上传?

import React, {Component} from "react";

class FetchUpload extends Component {
    constructor(props) {
        super(props);
        this.fileInput = React.createRef();
    }

    upload = () => {
        const data = new FormData();
        data.append("file", this.fileInput.current.files[0]);  //相当于 input:file 中的name属性
        fetch("http://127.0.0.1:3001/file/upload", {
            method: "POST",
            body: data
        }).then(response => console.log(response))
    };
    render() {
        return (
            
) } } export default FetchUpload;

这个方法比较投机取巧,就是将input:type中的数据append到FormData中,FormData会将数据编译成键值对,这样可以被fetch发送至后台(不仅仅限于fetch,也可以是ajax或者axios等等)。不过这种方法有个致命的问题,那就是会有跨域问题。对于这个问题,笔者会在博客末尾提供相关解决方案。

文件上传解决方案--fetch+form

这个方案看小标题和前面的内容,相信大家都能猜到是什么样子了。下面直接上代码:

import React, {Component} from "react"

class FormUpload extends Component {
    submit = (e) => {
        e.preventDefault();
        let formData = new FormData(e.target);
        fetch("http://127.0.0.1:3001/file/upload", {
            method: "POST",
            body: formData //自动将input:file的name属性与文件对象组合成键值对
        }).then(response => console.log(response))
    };

    render() {
        return (
            
) } } export default FormUpload;

总的来说,这个方法和第二中方法在原理上是相同的,只是获取的文件数据不是直接从input:type中获取的,而是从form的提交事件中获取的,其他的没什么变化,所以也会遇到跨域的问题。

后台组成

该博客的demo后台是express写的,所以不管是跨域管理还是接收并保存文件都是基于Node模块。

跨域管理

笔者常用的Node服务跨域解决方案是第三方库cors。当然cors除了是这个第三方库的名字,也有比较重要的W3C标准,它对解决浏览器跨域问题起到重要的作用,不过该博文的重点不在这所以不作赘述,相关的使用方法都在文末的demo里,有兴趣的朋友可以尝试用用,真的很high!

接收并保存文件

因为express自身的request对象不包含上传过来的文件对象,所以必须要用到第三方库multer。负责处理multipart/form-data 类型的表单数据和保存相关资源的作用。

小提示

利用multer初始化一个upload中间件对象时候需要指定一个“标志符”,比如:

let upload = multer({storage: storage}).single("file");

这里的标识符是file,对应前面代码中的:



data.append("file", this.fileInput.current.files[0])

这是一个不算大的坑,所以大家使用时候多多关注。

最后笔者奉上准备好的demo,有兴趣的话可以download下来耍耍。当然里面还包含了下一篇文件下载的代码,大家可以也顺带看看。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/98769.html

相关文章

  • [ 一起React系列 -- 9 ] React中的文件下载

    摘要:本篇所说的文件下载也是基于和或者都行。的返回值是一个有意思的对象,它包含了很多方法,其中一个方法就是。通过的响应头获取到文件名。接下来就是对标签的一系列操作,然后模拟点击事件触发下载动作。 距离上次博文更新已经快一个月了,期间忙于各种事情无法脱身。今天难得闲暇 and then 就来更新啦...上篇中我们了解了下载React中如何实现文件的上传,虽然不算什么高大上的技术但实际开发的时候...

    Jacendfeng 评论0 收藏0
  • JS框架 - 收藏集 - 掘金

    摘要:现在回过头总结,才又进一步的揭开了闭包的一层后台管理系统解决方案前端掘金基于系列的后台管理系统解决方案。什么是继承大多数人使用继承不外乎是为了获得基于的单页应用项目模板前端掘金小贴士本项目已升级至。 关于js、jq零碎知识点 - 掘金写在前面: 本文都是我目前学到的一些比较零碎的知识点,也是相对偏一点的知识,这是第二篇。前后可能没有太大的相关性,需要的朋友可以过来参考下,喜欢的可以点个...

    wenyiweb 评论0 收藏0
  • [ 一起React系列 -- 10 ] i18n

    摘要:假如有这么一段句子这件衣服是人民币如果我们想将一个数字以人民币的形式写进去的话可以这么做最终显示结果是这件衣服是人民币其实它做了两件事一个是加符号,另一个是加分隔符。同时表示人民币,表示美元。 今天来介绍一个非常international的东西。 i18n国际化(internationalization)的简称。之所以叫i18n,是因为字母i和n之间有18个字母,所以才叫i18n。不...

    biaoxiaoduan 评论0 收藏0
  • [ 一起React系列 -- 12 ] React-Router4 (2)

    摘要:验证路由所谓的验证路由其实就是该路由的外层加了一层验证机制,有授权的用户才能进入,反之都无法进入。一起学系列也随着这篇的结束而告一段落了。大家一起加油最后再献上和本篇博文有关的代码链接和示例页面 时隔那么久,博主终于从睡梦中醒来开始更新博客啦!为自己的勤劳欢呼...(pia pia pia打脸)!本次我们接着上一篇博客继续聊React-Router4。上篇我们主要了解了React-Ro...

    chaos_G 评论0 收藏0
  • [ 一起React系列 -- 11 ] React-Router4 (1)

    摘要:中的包中的包主要有三个和。的理念上面提到的理念是一切皆组件以下统一称组件。从这点来说的确方便了不少,也迎合一切皆组件的理念。组件是中主要的组成单位,可以认为是或的路由入口。将该标示为严格匹配路由。的属性追加一条。 2019年不知不觉已经过去19天了,有没有给自己做个总结?有没有给明年做个计划?当然笔者已经做好了明年的工作、学习计划;同时也包括该系列博客剩下的博文计划,目前还剩4篇:分别...

    tinysun1234 评论0 收藏0

发表评论

0条评论

Travis

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<