最近项目用的是Angular框架,但是并没有使用angular的组件库ant design,公司选择自己封装组件库,那么,很多的功能与样式实现就必须基于对原生元素的理解了。
其中最基本和常用的大概就是上传和下载了。自己做了之后才知道,上传不是像vue一样只使用FormData将上传的文件和信息传递给后端就可以的,而且下载的资源放置也不是单纯依靠 “window.location.href” 就能控制直接下载的,以下是我遇到的问题记录:
1.上传
上传使用的是原生的input:file元素,原生的input元素样式几乎不适用与大多数场合,大多数的样式要求是:
输入框获取焦点后进入资源页面选择文件,然后显示在输入框内,布局为:
<div class="file"> <!-- 选择文件: --> <span>选择文件</span> <span class="fileinput-button"> <input [(ngModel)]="form.file_name" placeholder="请选择"/> <input class="fileUp" type="file" (change)="handleUpload($event)"/> </span> </div>
样式为(scss):
margin-bottom: 32px; .fileinput-button { position: relative; display: inline-block; overflow: hidden; } .fileinput-button input { @include input; padding:11px 15px; background: $darkBg; outline:0; border:1px solid $line; color:$line; &.fileUp{ position: absolute; right: 0px; top: 0px; opacity: 0; -ms-filter: "alpha(opacity=0)"; } } }
样式搞定后,完成功能时有遇到一个之前混淆的概念,在input中有个onChange事件,将返回变化事件作为参数给处理的函数,这里要注意:
上传的不是直接的文件,而是change的事件,上传的文件存放在e.target.files里面!因为可以同时选择多个文件,所以e.target.files是 一个数组
handleUp(e){ //e是event事件;单个上传的文件是e.target.files[0] }
现在就可以拿后端提供的文件调用接口实现上传了
2.下载
之前项目需求用vue直接使用 “window.location.href” 就可以解决当时的下载需求。
这次上传的资源文件都统一放在minio里面(一个远程的服务)。在文件上传成功后,使用window.location.href下载的时候,竟然直接打开了那个获取资源的地址中要下载的文件。
不应该是这样,下载也可使用blob实现,俗称:创建一个a元素执行下载,然后悄悄remove掉
//fetch就是向地址发送访问请求,response.status ==200 表示成功访问
fetch(res.url).then(response => { if (response.status == 200) return response.blob()}).then(blob => { // 创建a标签 const link = document.createElement("a"); const url = URL.createObjectURL(blob); // download属性 link.setAttribute("download", e.file_name); // href链接 link.setAttribute("href", url); document.body.appendChild(link); // 自执行点击事件 link.click(); document.body.removeChild(link); }) .catch(error => { console.log("failed. cause:", error); });
事后请教了小伙伴才知道,存放在远程的资源在下载的时候,是需要将资源的路径去拿到文件,然后再对其文件流进行解读再生成原文件