记录-文件上传和下载-小坑
- 文件下载
- 坑
- 通用封装
- 文件上传
- 坑
1. 文件下载
-
针对url(http://xxxxxx/a.zip) 的下载
- window.open(
url, '_self') // 是能下载的链接,就直接下载
// 以下代码可以控制台直接跑起来 var data = ['<a id="a"><b id="b">hey!</b></a>']; // data,用数组包裹 var blob = new Blob(data, {type : 'application/octet-stream;charset=utf-8'}); // 生成Blob对象, Blob对象表示一个不可变、原始数据的类文件对象 var url = window.URL.createObjectURL(blob) // 生成一个url:可以指向 File 对象或 Blob 对象。 window.open(url) // 打开url,如果是下载链接则下载 - window.open(
-
针对文件流的下载
接口给到一个文件流的话,其实也可以和上面的方法一样去下载。但是缺点是需要用户自己去手动输入 下载的文件名和格式,否则是没有后缀的文件,会显示打不开
以下我们用dom的download属性下载
const downFile = (data, filename = '模板.xlsx', headerType = 'application/octet-stream;charset=utf-8') => { const blob = new Blob([data], { type: headerType }) // 生成Blob对象, Blob对象表示一个不可变、原始数据的类文件对象 const url = window.URL.createObjectURL(blob) // 生成一个url:可以指向 File 对象或 Blob 对象。 const dom = document.createElement('a') dom.href = url dom.download = decodeURI(filename) // 用dom的download下载,可以设置默认文件名 dom.style.display = 'none' document.body.appendChild(dom) dom.click() dom.parentNode.removeChild(dom) // 释放内存 window.URL.revokeObjectURL(url) // 释放内存 }!!!此处有个坑,需要特别注意:
文件流是从接口拿的,请求的axios需要配置 responseType !!!
export const get_xxx = (params) => { return axios({ method: 'get', url: "/xxxx", responseType: "blob", // 拿文件流需要配置这个 params }) } // axios 内: // `responseType` 表示服务器响应的数据类型, // 可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream' responseType: 'json', // 默认的 -
最终封装
/** * 方法说明 下载文件, 有2种形式, 1. url (例如: http://xxxxx/a.zip) 2. 文件流, 且需要默认文件名 * @method downFile * @param{object} url data filename headerType * * 使用示例: * 形式1: downFile({ url: 'http://xxxxx/a.zip' }) * 形式2: downFile({ * data: 'xxx文件流', * filename: '模板.xlsx', // 可选, 默认'模板.xlsx' * headerType: 'application/octet-stream;charset=utf-8', // 可选 默认'application/octet-stream;charset=utf-8' * }) */ export const downFile = function (obj) { if (obj.url) { // 形式1 url (例如: http://xxxxx/a.zip) window.open(obj.url) } else { // 形式2 文件流, 且需要默认文件名 const { data, filename = '模板.xlsx', headerType = 'application/octet-stream;charset=utf-8' } = obj const blob = new Blob([data], { type: headerType }) const url = window.URL.createObjectURL(blob) const dom = document.createElement('a') dom.href = url dom.download = decodeURI(filename) // 用dom的download下载,可以设置默认文件名 dom.style.display = 'none' document.body.appendChild(dom) dom.click() dom.parentNode.removeChild(dom) // 释放内存 window.URL.revokeObjectURL(url) // 释放内存 } }
2. 文件上传
先说一下小坑,憋着难受 ( ̄. ̄||)
如果响应头: Access-Control-Allow-Origin: *
白名单直接配置了*的话,前端就不能带cookie !!!!
否则接口会报跨域的错误
接下来继续讲文件上传
-
用ui组件 (此处用的iview)
<Upload type="drag" name="excelFile" // 如果接口需要加参数,则加个name :headers="headers" action="http://xxxxxx/import"> <div style="padding: 10px 0"> <Icon type="ios-cloud-upload" size="52" style="color: #39f"></Icon> <p>点击或拖拽上传文件</p> </div> </Upload> 注意点:公司内部平台,一般来说,都需要设置请求头 不要加Content-Type: multipart/form-data; ( 文件上传默认会自动适配Content-Type, 千万不要在额外加 ) 其他的请求头需要多少,就自行加上 此处有个坑点 ui组件配置 with-credentials(支持发送 cookie 凭证信息, 默认false,如果要改为true 要小心),这个坑点就是上面写的然后,如果接口需要加参数,则加个 name="excelFile"
-
自己写上传
-
用axios上传
最好,重新引入axios,因为,项目内的axios可能被封装过,Content-Type 可能已经被动过了,要文件上传能够成功,这个Content-Type不能动,他会自动识别到是文件上传multipart/form-data + 文件标识
import Axios from 'axios' const upload = (file) => { // file 是 File对象 const formData = new FormData() formData.append('excelFile', file) // 接口需要传参excelFile,具体情况具体分析 let res = await Axios.post('http://xxxx/import', formData, { headers: { 'Token': xxx, 'System-Host': xx } }) res = res.data console.log(res) } -
用fetch上传
const upload = (file) => { // file是 File 对象 const formData = new FormData() formData.append('excelFile', file) // 接口需要传参excelFile,具体情况具体分析 let res = await fetch('http://xxxxx/import', { body: formData, credentials: 'omit', // 不传cookie headers: { 'Token': xxx, 'System-Host': xx }, method: 'POST' // *GET, POST, PUT, DELETE, etc. }) res = await res.json() console.log(res) }
-