-
Vue实现文件上传和文件下载
2018-08-22 22:09:55文件下载: 文件下载通常有几种方法 1.通过url下载 2.location.href ...前端第一个实现是使用a标签, 第二种方式: 这个方法是直接把 DataURLs 或者 BlogURLs 传到浏览器地址中触发下载。有两种...文件下载:
文件下载通常有几种方法
1.通过url下载
2.location.href
3.form提交直接下载
4.HTML5 a.download结合blob对象进行下载
第一种方式:
第一种方法是前后端的接口只给了一个API请求:
前端第一个实现是使用a标签,
第二种方式:
这个方法是直接把 DataURLs 或者 BlogURLs 传到浏览器地址中触发下载。有两种方式:window.location.href = urls; // 本窗口打开下载 window.open(urls, '_blank'); // 新开窗口下载
this.content = content this.filename = filename const blob = new Blob([this.content]) if (window.navigator.msSaveOrOpenBlob) { // 兼容IE10 navigator.msSaveBlob(blob, this.filename) } else { // chrome/firefox let aTag = document.createElement('a') aTag.download = this.filename aTag.href = URL.createObjectURL(blob) aTag.click() URL.revokeObjectURL(aTag.href) }
第四种form表单
不需要我们处理返回二进制流直接下载,非常方便
form的action设置为接口地址,method设置为post,Post到后台的数据设置为input的属性 name = key,value = value的形式,如果有多个key、value的值要传递,那么就设置多个input来分别储存单个的key、value;
如果请求的接口可以不需要参数,那么input还是必须要一个,如果不要得话 会引起接口报错
原理:form的action相当于一个浏览器本页签/页面的一个请求,不会被后台,前台的路由拦截。所以能够提交成功。注意点:如果设置method为get,在action中的uri添加了参数的话,想用这个参数替代input的key、value形式来提交到后台,这参数是没有效果的,后台拿不到这些参数,真正的参数还是以input的name、value的形式储存,在submit方法执行后传递到后台。
这样我们就是实现了文件下载,但是表单提交的数据一般是简单的键值对,如果传参比较复杂可以考虑将表单序列化提交。因为项目是基于vue的,而且提交的请求参数涉及很多参数,比较复杂,所以采用了方法三来实现
axios.post('/rest/inventory/oh_status/info/excel', { site: this.selectedsite, bu: this.selectedbu, ohHealthStatus: this.selectedtitle, ohHealthRootcause: this.selectedblock, search: this.search, sort: this.sort }, {responseType: 'arraybuffer'}).then(this.ExportFile).catch(function (error) { console.log(error) }) this.content = content this.filename = filename const blob = new Blob([this.content]) if (window.navigator.msSaveOrOpenBlob) { // 兼容IE10 navigator.msSaveBlob(blob, this.filename) } else { // chrome/firefox let aTag = document.createElement('a') aTag.download = this.filename aTag.href = URL.createObjectURL(blob) aTag.click() URL.revokeObjectURL(aTag.href) }
注意我们发送请求的时候一定要写上responseType,
{responseType: 'arraybuffer'}
否则下载下来的文件打不开!!!文件上传
文件上传通常使用form表单,但是有时候我们不想要用表单,ES6的fromData来实现handleGetFile (data) { this.file = data let formdata = new FormData() formdata.append('file', this.file) formdata.append('submit', false) let config = { headers: { 'Content-Type': 'multipart/form-data' } } axios.post('/rest/master_data/ct2r/odin_delivery_metrics/cvc/file_upload_review', formdata, config).then(this.sendFileSucc) },
首先 我们获取完文件之后,创建FormData对象,配置头部,发送该请求就OK了,别忘了让后台将接收头部请求改为formdata的格式
如果文件是图片或者视频的话,部分浏览器会直接打开,非下载,这个时候我们可以在下载链接 url 后面加上
?response-content-type=application/octet-stream
这个参数可以实现点击下载功能。 -
vue实现文件上传
2018-03-28 10:57:55文件上传的传统方式是通过 form 表单提交,但是今天我们将换一种方式来实现这个功能。同一口味的东西吃多了还会腻呢,所以适当的时候换一换口味还是有必要的,好了,直接进入正文。首先,来介绍一下我们今天的主角 -...文件上传的传统方式是通过 form 表单提交,但是今天我们将换一种方式来实现这个功能。同一口味的东西吃多了还会腻呢,所以适当的时候换一换口味还是有必要的,好了,直接进入正文。
首先,来介绍一下我们今天的主角 --- FormData,是的,就是他,虽然他和 form长得有点像,但是是2个不一样的东西。对于form相信大家一定不陌生,所以我们重点介绍一下 FormData。
FormData对象可以组装一组用 XMLHttpRequest 发送请求的键/值对.它可以灵活方便的发送表单数据,因此可以独立于表单使用.如果把表单的编码类型设置为 multipart/form-data,则通过 FormData 传输的数据格式和表单通过 submit() 方法传输的数据格式相同.<input type="file" class="file"> // 通过file来选择需要上传的文件
var formData = new FormData() // 声明一个FormData对象 var formData = new window.FormData() // vue 中使用 window.FormData(),否则会报 'FormData isn't definded'
formData.append('userfile', document.querySelector('input[type=file]').files[0]) // 'userfile' 这个名字要和后台获取文件的名字一样; //'userfile'是formData这个对象的键名
到这里,我们就已经成功实现了文件的上传,是不是觉得很简单?小伙伴们,赶紧动手试一试吧。var options = { // 设置axios的参数 url: '请求地址', data: formData, method: 'post', headers: { 'Content-Type': 'multipart/form-data' } } this.axios(options).then((res) => {}) // 发送请求
-
Vue实现文件上传
2020-03-23 18:06:57Vue结合Vant进行文件上传 html: 调起手机文件夹及录像机上传视频: <van-uploader :after-read="afterRead" preview-size="38" upload-icon="plus" accept="video/*"> <span class="icon">򪜐...Vue结合Vant进行文件上传
html:
调起手机文件夹及录像机上传视频:
<van-uploader :after-read="afterRead" preview-size="38" upload-icon="plus" accept="video/*"> <span class="icon">򪜐</span> <span class="name">添加视频</span> </van-uploader>
调起手机文件夹及摄像头上传图片:
<van-uploader :after-read="afterRead" preview-size="38" upload-icon="plus" accept="image/*"> <span class="icon">򪜐</span> <span class="name">添加图片</span> </van-uploader>
调起手机文件夹及录音上传音频:
<van-uploader :after-read="afterRead" preview-size="38" upload-icon="plus" accept="audio/*"> <span class="icon">򪜐</span> <span class="name">添加音频</span> </van-uploader>
script:
data() { return { imgList: [], // 图片 videoList: [], // 视频 audioList: [], // 音频 } } methods: { afterRead(file, detail) { Toast.loading({ message: "文件上传中,请稍后~", forbidClick: true, duration: 0 }); file.status = "uploading"; file.message = "上传中"; var param = { type: "image" }; var that = this; console.log("file", file); if (file.file.type.indexOf("video") >= 0) { param.type = "video"; } if (file.file.type.indexOf("image") >= 0) { param.type = "image"; } if (file.file.type.indexOf("audio") >= 0) { param.type = "audio"; } this.upload(file, param, res => { if (param.type == "audio") { that.audioList.push({ seconds: res.seconds, url: res.url }); } else if (param.type == "video") { that.videoList.push({ type: param.type, url: res }); } else { that.imgList.push({ type: param.type, url: res }); } file.status = "succeed"; file.message = ""; Toast.clear(); console.log(this.imgList, '图片') console.log(this.videoList, '视频') console.log(this.audioList, '音频') }); }, }
upload() { // oss上传 import OSS from 'ali-oss' import md5 from 'js-md5' import {Toast} from 'vant'; const clientOss = new OSS({ region: 'oss-cn-beijing', endpoint: 'https://xxxx.xxxxxxxxxxxxxx.com', // 地址 cname: true, // 云账号AccessKey有所有API访问权限,建议遵循阿里云安全最佳实践,部署在服务端使用RAM子账号或STS,部署在客户端使用STS。 accessKeyId: 'xxxxxxxxxxxx', // ID accessKeySecret: 'xxxxxxxxxxxxx', bucket: 'xxxxxxxxxxxxxx', secure:true }) // oss上传图片与视频 export function upload(params, data, callback) { // 文件类型 const file_type = params.file.type.split('/')[0] // 文件格式 const file_format = params.file.type.split('/')[1] // 图片格式 const acceptImage = ['jpg', 'jpeg', 'png', 'gif'] // 视频格式 const acceptVideo = ['mp4'] // 音频格式 const acceptAudio = ['mp3'] // 1、判断文件类型是否正确 if (data.type !== file_type) { Toast('请上传正确的文件类型!') callback({ status: 'error' }) return false } // 2、判断文件格式 if (file_type === 'image') { const isAccept = acceptImage.includes(file_format.toLowerCase(), 0) if (!isAccept) { Toast('文件格式只支持PNG,JPG,GIF,请重新上传!') callback({ status: 'error' }) return false } } else if (file_type === 'video') { const isAccept = acceptVideo.includes(file_format.toLowerCase(), 0) } else if (file_type === 'audio') { const isAccept = acceptAudio.includes(file_format.toLowerCase(), 0) if (!isAccept) { Toast('文件格式只支持MP3,请重新上传!') callback({ status: 'error' }) return false } } // 3、判断文件大小是否超出限制 if (file_type === 'image') { const file_size = params.file.size / (1 * 1024 * 1024).toFixed(1) if (file_size >= 5) { Toast('文件大小超出5M,请重新上传!') callback({ status: 'error' }) return false } else { // 4、上传文件 // 文件存储名称,key const file_name = md5(params.file.name.split('.')[0] + new Date().getTime()) + '.' + file_format // 第一个参数表示上传到OSS的Object名称,第二个参数表示本地文件或者文件路径 clientOss.put('images/' + file_name, params.file).then(res => { callback(res.url) }).catch((err) => { console.log('error:', err) return false }) } } else if (file_type === 'video') { const url = URL.createObjectURL(params.file) const audioElement = new Audio(url) audioElement.addEventListener('loadedmetadata', () => { const file_time = Math.floor(audioElement.duration) if (file_time > data.len) { Toast('视频时长不可超过' + data.len + '秒,请重新上传!') callback({ status: 'error' }) return false } else { // 4、上传文件 // 文件存储名称,key const file_name = md5(params.file.name.split('.')[0] + new Date().getTime()) + new Date().getTime() + '.' + file_format // 第一个参数表示上传到OSS的Object名称,第二个参数表示本地文件或者文件路径 clientOss.put('images/' + file_name, params.file).then(res => { callback(res.url) }).catch((err) => { console.log('error:', err) return false }) } }) } else if (file_type === 'audio') { const url = URL.createObjectURL(params.file) const audioElement = new Audio(url) audioElement.addEventListener('loadedmetadata', () => { const file_time = Math.floor(audioElement.duration) if (file_time > data.len) { Toast('音频时长不可超过' + data.len + '秒,请重新上传!') callback({ status: 'error' }) return false } else { // 4、上传文件 // 文件存储名称,key var name = ""; if (params.file.name) { name = params.file.name } else { var date=new Date() name =date.getFullYear()+"_"+ new Date().getTime() } const file_name = md5(name.split('.')[0] + new Date().getTime()) + new Date().getTime() + '.' + file_format // 第一个参数表示上传到OSS的Object名称,第二个参数表示本地文件或者文件路径 clientOss.put('images/' + file_name, params.file).then(res => { const param = {url: res.url, seconds: file_time} callback(param) }).catch((err) => { console.log('error:', err) return false }) } }) } } export function imgOverSize(params, data, callback) { const file_size = params.file.size / (1 * 1024 * 1024).toFixed(1) if (file_size >= 5) { Toast('文件大小超出5M,请重新上传!') return true }else{ return false; } }
ok,完成! -
vue实现文件上传功能
2020-10-18 05:59:38主要为大家详细介绍了vue实现文件上传功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 -
node+vue实现文件上传功能
2020-10-15 06:56:41主要介绍了node+vue实现文件上传功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 -
springboot+vue实现文件上传下载
2021-01-18 17:04:45本文实例为大家分享了springboot+vue实现文件上传下载的具体代码,供大家参考,具体内容如下 一、文件上传(基于axios的简单上传) 所使用的技术:axios、springboot、vue; 实现思路:通过h5 :input元素标签进行... -
vue实现文件上传读取及下载功能
2020-10-16 08:43:50主要为大家详细介绍了vue实现文件上传读取及下载功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 -
vue 实现文件上传
2020-11-14 18:53:21(一)首先实现html、css布局 代码: <template> <div class="image-uploader"> <img :src="uploadIcon" class="icon"/> <p>Drag your images here</p> <p>OR</p&...(一)首先实现html、css布局
代码:
<template> <div class="image-uploader"> <img :src="uploadIcon" class="icon"/> <p>Drag your images here</p> <p>OR</p> <div class="real-btn"> SELECT A FiLE <input type="file" @change="inputChange" class="hide-btn"> </div> </div> </template> <script> import uploadIcon from '../assets/upload.png' export default { name: 'imageUpload', data () { return { uploadIcon: uploadIcon } } } </script> <style scoped> .image-uploader { margin: 20px; border: 3px dashed #fff; background: #2196F3; padding: 10px; text-align: center; color: #fff; border-radius: 10px; font-weight: 500; } .real-btn { cursor: pointer; position: relative; padding: 10px 20px; background: #fff; border-radius: 10px; color: #2196F3; } .hide-btn { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; } .icon { width: 50px; height: 50px; } </style>
到这一步,样式就算是写完了
注意!!
由于只有 input 的 type 等于 file 的时候才能调起电脑文件夹,所以 SELECT A FiLE 这个按钮是与 <input type="file"> 这个元素重叠的,点击 SELECT A FiLE 这个按钮其实是 点击 <input type="file">,然后将 input 这个标签隐藏
最后通过 opacity: 0;将真实的input 隐藏
(二)实现拖拽上传
(1)实现拖拽的效果需要 使用两个方法:dragEnter、dragLeave
这时候又遇到坑了,我在最外层父元素上绑定 dragEnter、dragLeave
当将图片在父元素区域内拖动时,会不断触发 dragEnter、dragLeave,而不是 只有进来和出去触发,经过了解解释如下:
它是每进入一个新元素的同时就退出上一个元素,当退出父元素时,就不会有下一个进入的元素了, 所以进入的元素与退出的的元素相等,所以我们需要记录上次移入的节点
// 拖拽进入上传文件区 dragEnter (e) { this.currentTarget = e.target // 当前进入的元素 this.isDragging = true }, // 拖拽离开上传文件区 dragLeave (e) { if (e.target === this.currentTarget) { this.isDragging = false } }
(2)拖拽进去松手之后
触发 drop 事件
drop (e) { this.isDragging = false // 解决 e.dataTransfer.files 经常为空的问题 var file = [] file.forEach.call(e.dataTransfer.files, function (item) { file.push(item) }, false) },
拖进去的文件 在 e.dataTransfer.files 这个字段里,我们需要转成数组
(3)通过 input 上传
<input type="file" @change="inputChange" class="hide-btn">
async inputChange (e) { const base64 = await this.getBase64(e.target.files[0]) this.getImageUrl(base64, e.target.files[0].name) },
上传结果图:
完整代码:
<template> <div class="image-uploader" @dragenter="dragEnter" @dragleave="dragLeave" @drop.prevent="drop" @dragover.prevent :class="[ isDragging ? 'isDraging' : '' ]" > <img :src="uploadIcon" class="icon"/> <p>Drag your images here</p> <p>OR</p> <div class="real-btn" :class="[ isDragging ? 'isDraging-btn' : '' ]" > SELECT A FILE <input type="file" @change="inputChange" class="hide-btn"> </div> <!-- 上传图片展示列表 --> <div v-show="files.length > 0" class="file-list"> <div v-for="(fileItem) in files" :key="fileItem.index" class="list-item" > <img :src="fileItem.url" alt=""> <div>{{ fileItem.name }}</div> </div> </div> </div> </template> <script> import uploadIcon from '../assets/upload.png' import axios from 'axios' export default { name: 'imageUpload', data () { return { uploadIcon: uploadIcon, isDragging: false, // 是否正在拖拽 currentTarget: null, // 上一个dragEnter的元素 files: [] // 文件上传列表 } }, methods: { // 拖拽进入上传文件区 dragEnter (e) { this.currentTarget = e.target this.isDragging = true }, // 拖拽离开上传文件区 dragLeave (e) { if (e.target === this.currentTarget) { this.isDragging = false } }, // drop 是指将文件拖入父元素 松手触发的操作 // 必须阻止 dragover 的默认行为 不然 drop 不生效 // drop 也要阻止默认行为 不然拖进去后 浏览器自动打开该文件 drop (e) { this.isDragging = false // 解决 e.dataTransfer.files 经常为空的问题 // 把累数组转化成数组 var file = [] file.forEach.call(e.dataTransfer.files, function (item) { file.push(item) }, false) // Array.from(e.dataTransfer.files).forEach((item) => { file.push(item) }) // 遍历对象 存入文件数组 file.forEach(async (item) => { const base64 = await this.getBase64(item) this.getImageUrl(base64, item.name) }) }, async inputChange (e) { const base64 = await this.getBase64(e.target.files[0]) this.getImageUrl(base64, e.target.files[0].name) }, // 图片上传cdn 生成链接 getImageUrl (base64, fileName) { const url = 'https://bird.ioliu.cn/v1?url=http://hn216.api.yesapi.cn' axios.post(url, { file: base64, s: 'App.CDN.UploadImgByBase64', app_key: '228290AC6E185D2121CD5878EDC4D010', file_name: fileName }).then((res) => { this.files.push({ url: res.url, name: fileName, index: Math.random() }) }).catch(() => { // 使用默认的 const res = {url: 'https://dss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=191936283,2923048863&fm=26&gp=0.jpg'} this.files.push({ url: res.url, name: fileName, index: Math.random() }) }) }, // 图片转化成base64 便于上传cdn转成链接 getBase64 (file) { return new Promise((resolve, reject) => { let reader = new FileReader() if (file) { // 将文件以Data URL形式读入页面 let imgUrlBase64 = reader.readAsDataURL(file) reader.onload = function (e) { resolve(reader.result) } } }) } } } </script> <style scoped> .image-uploader { margin: 20px; border: 3px dashed #fff; background: #2196F3; padding: 10px; text-align: center; color: #fff; border-radius: 10px; font-weight: 500; } .image-uploader.isDraging { background: #fff; border: 3px dashed #2196F3; color: #2196F3; } .real-btn { cursor: pointer; position: relative; padding: 10px 20px; background: #fff; border-radius: 10px; color: #2196F3; } .real-btn.isDraging-btn { background: #2196F3; color: #fff; } .hide-btn { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; } .icon { width: 50px; height: 50px; } .file-list { display: flex; flex-wrap: wrap; margin-top: 10px; } .file-list img { width: 100%; } .list-item { width: 50%; } </style>
(1)可以判断一下上传的文件类型,通过type字段,然后做相应的处理
比如类型不正确,然后进行报错提示
(2)还可以拿到上传文件的大小,通过size字段
-
vue 实现文件上传和文件下载
2018-09-01 08:58:00vue实现文件上传和文件下载 转载于:https://www.cnblogs.com/knuzy/p/9569167.html -
vue 文件及描述信息一起上传_vue实现文件上传读取及下载功能
2020-12-18 19:25:30本文实例为大家分享了vue实现文件上传读取及下载的具体代码,供大家参考,具体内容如下文件的上传利用input标签的type="file"属性,读取用FileReader对象,下载通过创建a标签实现下载export default {data () {... -
springmvc+vue实现文件上传
2018-06-10 10:46:34需求:spring+vue实现文件上传思路使用Element UI中的上传插件,在进行分装,然后传入java,使用java上传文件之后,保存文件所对应的url地址,以便下次访问时候使用。前端代码插件的使用具体见element UI的官方文档 ... -
Spring Boot+Vue实现文件上传以及在线预览
2020-09-03 09:52:07利用spring boot和vue实现文件上传以及在线预览 -
vue 附件上传获取附近内容_vue实现文件上传读取及下载功能
2021-01-12 08:19:03本文实例为大家分享了vue实现文件上传读取及下载的具体代码,供大家参考,具体内容如下文件的上传利用input标签的type="file"属性,读取用FileReader对象,下载通过创建a标签实现下载export default {data () {... -
SpringBoot+Vue实现文件上传+预览
2020-09-02 22:46:32从松哥的微信公众号上面看到了SpringBoot+Vue实现文件上传+预览的视频教程,如下图所示: 跟着做,使用IDEA一遍看一边做,没想到由于自己马虎将日期SimpleDateFormat simpleDateFormat = new SimpleDateFormat("/... -
vue 附件上传获取附近内容_vue实现文件上传功能
2020-12-20 01:40:22vue 文件上传,供大家参考,具体内容如下首先 先说一下想要实现的效果就如截图所见,需要将企业和需要上传的文件提交到后台处理,那么接下来就说如何实现vue 实现vue 页面代码class="upload-demo"ref="upload"action... -
用vue实现文件上传
2019-09-16 09:46:47使用Upload组件实现文件上传,如果要使用upload,需要引入ElementUI,所以一般建议,如果使用了ElementUI做UI控件的话,则可以考虑使用Upload组件来实现文件上传。 <el-upload style="display:inline" :show-... -
vue实现文件上传mp4_.NET Core 3.1 WebAPI+Vue+Element UI实现文件上传
2021-02-01 08:40:22(给DotNet加星标,提升.Net技能)转自:吕小不cnblogs....在接下来的内容主要还是针对单文件上传,对于多文件的上传,我暂且尚未研究成功。其中pictureoptions类,由于我把关于图片上传相关的...