input输入框实现文件上传

1,678 阅读3分钟

自定义文件上传组件

前提:

本来是可以用ant Design的Upload组件完成文件上传的,但由于需要把文件和其他表单信息一起传递给后台,所以放弃了使用蚂蚁现成的Upload组件,使用Input组件改造.

html部分:

<Input 
  type="file" id="upload-file" 
  multiple accept=".xls,.xlsx" 
  onchange={(e)=>{e.persist();
  /*e.target.files就是上传的文件的信息*/
}}/>

因为只能上传Excel文档,所以我使用accep属性进行了现在.提示:网上有大佬指出这里应该填写application/vtn...一长串的东西,我试了一下,没有用,还是这种文件后缀名有效. multiple表示可以选择多个文件.

js部分:

export async function add({file, url}) {    
    const finalUrl = url;    
    const formData = new FormData();    
    formData.append('file', file, file.name);    
    return fetch(finalUrl, {
        method: 'POST',      
        body: formData,    
    }).then((response) => {   
       return response      
    }) .catch((err) => {      
       console.log('出错啦')        
       return { err };      
    });
}

export async function add({ url, file }) {    const finalUrl = url;    const formData = new FormData();    formData.append('file', file, file.name);    fetch(finalUrl, {        method: 'POST',        body: formData,    })    .then( (res) => {        return res.json()    })    .then((data) => {//data为上一个then方法return的值        console.log(data)        return data    })    .catch(err => {        console.log(err)    })
    //return 'hello world'}

由于fetch请求是一个异步请求,所以fetch以及后面的then和catch都会放在微任务队列中.由于catch后面没有同步的return语句,所以调用这个方法获得的就是undefined.假设把注释掉的那句return代码打开,那调用add方法的函数会得到'hello world'字符串.

为了能够将获取到的结果返回给调用add方法的函数,则应该在该add方法中使用await,才能把请求后的结果返回给调用者.

export async function add({ url, file }) { 
    const finalUrl = url;  
    const formData = new FormData(); 
    formData.append('file', file, file.name);  
    const response = await fetch(finalUrl, {        
        method: 'POST',      
        body: formData, 
    });
    return await response.json()   
}

这里又涉及到了异步的问题.谈到异步肯定会想到promise和async/await.

Promise和async/await的比较:

一般有异步的地方,任务队列肯定少不了.至此,再谈下事件循环的问题.

css部分:

如果直接这么做,样式非常丑,并且按钮中的文字只能是"选择文件",有时候产品的需求是"导入文件"之类的.

<a 
   href="javascript:;" 
   style={{
       padding: 4,color: '#000', borderWith: 1, borderStyle: 'solid', borderColor: '#ddd', borderRadius: 4}}
>   <Input        
       type="file"        
       style={{lineHeight: 1.3,position: 'absolute',left: 0, right: 0, top: 0, opacity: 0}}  
       id="uploadUid"        
       accept=".xlsx,.xls"    
       onChange={(e) => {
           e.persist();//关于input框的onchange事件获取不到e.target的问题只需要在赋值前加上 e.persist() 即可
           this.setState({fileList: [e.target.files[0].name]})}}/>   
   <span>{fileList.length > 0 ? "重新导入": '导入文件'}</span>
</a>    
<span>{fileList.length == 0 ? '未选择文件' : '文件名'}</span>

这样改造后,上传文件的组件的按钮中的文字也可以随心所欲地修改,并且也会像原生那样显示文件名,在没有选择文件的时候显示"未选择文件"的提示信息.

fetch请求资源

Fetch是基于promise设计的。Fetch的代码结构比起ajax简单多了,参数有点像jQuery ajax。但是,一定记住fetch不是ajax的进一步封装,而是原生js,没有使用XMLHttpRequest对象。

fetch跨网络异步获取资源

跨域

fetch与Ajax,axios的区别

axios是对原生XHR的封装

promise, async/await

XMLHttpRequest

JSON() blog.csdn.net/zty5556666/…

如果有不正确的地方,欢迎指正.如果有更好的解决方案,感谢分享!

总结:自定义文件上传组件其实还是非常地简单,只是前期自己不断地摸索会花费很多时间,但在摸索的过程中自己能够学到更多的知识.