ToB企服应用市场:ToB评测及商务社交产业平台

标题: 【前端】-【前端文件操作与文件上传】-【前端接受后端传输文件指南】 [打印本页]

作者: 刘俊凯    时间: 2024-7-16 09:45
标题: 【前端】-【前端文件操作与文件上传】-【前端接受后端传输文件指南】
前端文件操作与文件上传

一、前端文件上传有两种思路:
二、与文件相关的对象
三、file参数、blob切割文件、FileReader将文件转成base64,浓缩图/文本预览:
  1. <template>
  2.   <div>
  3.     <input type="file" name="file" @change="fileChange" />
  4.     <!-- 缩略图,文本预览 -->
  5.     <img style="width:200px;" :src="imgbase64" />
  6.     <button @click="submit">提交</button>
  7.   </div>
  8. </template>
  9. <script>
  10. import axios from "axios"
  11. import { fstat } from "fs";
  12. let _fileObj;
  13. export default {
  14.   name: 'HelloWorld',
  15.   data() {
  16.     return {
  17.       imgbase64: "",
  18.     }
  19.   },
  20.   methods: {
  21.     fileChange(e) {
  22.        let file = e.target.files[0]// files是个数组
  23.        _fileObj = file;
  24.        // file常用属性:size(大小)、type(类型)、name(文件名)
  25.       if (file.size > 10 * 24 * 24) {
  26.         alert("文件不能大于十兆")
  27.       }
  28.       if (file.type !== 'video/mp4') {
  29.         alert("必须是mp4")
  30.       }
  31.       // 使用blob的slice方法可以切割文件
  32.       let _sliceBlob = new Blob([file]).slice(0, 5000);// 切割二进制的0-5000位
  33.       // 将切割后的Blob对象转成File对象(第二个参数是文件名),之后就可以上传切割后的File对象
  34.       let _sliceFile = new File([_sliceBlob], "test.png");
  35.       
  36.       //将File对象或者Blob对象转成base64或text
  37.       let fr = new FileReader();
  38.       fr.readAsDataURL(_sliceFile);// readAsDataURL是转成base64的方法
  39.       let self = this;
  40.       fr.onload = function () {
  41.         // base64是异步的转换,通过onload方法获得转换结果
  42.         self.imgbase64 = fr.result// 直接将转换结果赋值给img的src,设置src的大小即可获得浓缩图
  43.         console.log(fr.result)// 打印结果见下图一
  44.       }
  45.     },
  46.     async submit() {
  47.     // 这部分的代码后面讲
  48.             let _formData = new FormData();
  49.         _formData.append("user", "asdasd");
  50.         _formData.append("file", _fileObj)
  51.         axios.post("/xx", _formData);
  52.     }
  53.     }
  54.   }
  55. }
  56. </script>
复制代码

四、formData:不但可以搭载文件,还可以搭载笔墨、input的其他输入
  1. <form action="xxx" method="post">默认情况下提交为query参数</from>
  2. <form action="xxx" method="post" enctype="multipart/form-data">enctype指定提交为formData</from>
复制代码
五、文件上传:将blob转成FormData上传
  1. async submit() {
  2.         let _formData = new FormData();
  3.     _formData.append("user", "asdasd");
  4.     _formData.append("file", _fileObj)
  5.     axios.post("/xx", _formData);
  6. }
复制代码
通过查看网络可以发现:
七、具体功能
  1. <template>
  2.   <div>
  3.     <input type="file" name="file" @change="fileChange" multiple />
  4.     <span v-for="item in imgList">{{ item.name }}</span>
  5.     <button @click="submit">提交</button>
  6.   </div>
  7. </template>
  8. <script>
  9. import axios from "axios"
  10. import { fstat } from "fs";
  11. let _fileObj;
  12. export default {
  13.   name: 'HelloWorld',
  14.   data() {
  15.     return {
  16.       imgList: [],
  17.     }
  18.   },
  19.   methods: {
  20.     fileChange(e) {
  21.       //多文件上传
  22.       // multiple的多文件上传其实很不友好,需要用户在选择文件时按住ctrl多选,否则就会变成单选
  23.       // 所以使用imgList数组将用户每次选择的内容都push进去
  24.       if (e.target.files.length > 1) {
  25.         
  26.         this.imgList.concat(e.target.files)
  27.       } else {
  28.         this.imgList.push(e.target.files[0]);
  29.       }
  30.       //切片上传
  31.       _fileObj = e.target.files[0]
  32.     },
  33.     async submit() {
  34.       // 遍历,一个一个上传
  35.       this.imgList.forEach((item) => {
  36.         let _formData = new FormData();
  37.         _formData.append(item.name + "file", item)
  38.         axios.post("/xx", _formData);
  39.       })
  40.     }
  41.   }
  42. }
  43. </script>
复制代码
  1. <template>
  2.   <div>
  3.     <input type="file" name="file" @change="fileChange" multiple />
  4.     <div>{{ precent }}%</div>
  5.     <button @click="submit">提交</button>
  6.   </div>
  7. </template>
  8. <script>
  9. import axios from "axios"
  10. import { fstat } from "fs";
  11. let _fileObj;
  12. export default {
  13.   name: 'HelloWorld',
  14.   data() {
  15.     return {
  16.       precent: 0
  17.     }
  18.   },
  19.   methods: {
  20.     fileChange(e) {
  21.       //切片上传,在上传的时候进行切片,文件改变时只赋值
  22.       _fileObj = e.target.files[0]
  23.     },
  24.     async submit() {
  25.       let size = 2 * 1024 * 1024;// 每次切片的大小,片为2m
  26.       let fileSize = _fileObj.size;
  27.       let current = 0;// 当前已经传了多少
  28.       // 断点续传,永久记录中断的地方,下次上传时直接从断点开始传
  29.       //localStorage.setItem(_fileObj.name, current);
  30.       while (current < fileSize) {
  31.         let _formData = new FormData();
  32.         _formData.append(_fileObj.name, _fileObj.slice(current, current + size))
  33.         await axios.post("http://localhost:4000/upload",_formData)
  34.         // 进度条可以用axios的onUploadProgress方法,且发送切片时可以并行发送请求,后续可以自行优化
  35.         this.precent = Math.min((current / fileSize) * 100, 100)
  36.         current += size;
  37.       }
  38.     }
  39.   }
  40. }
  41. </script>
复制代码
  File System Access API 允许直接读取、写入或生存对用户装备上的文件和文件夹的更改。从 Chrome 86 开始支持 File System Access API,目前只有基于 Chromium 系列的欣赏器全面支持,Safari 部分支持(支持读取,不支持写入和生存),而 Firefox 未支持。
  前端接受后端传输文件指南

一、前端把后端传过来的文件下载下来(后端返回给我们的文件一样平常是二进制的),有以下几种方式:
   几个告急的概念:
    文件下载流程:
(1)

(1)使用blob吸收后端传过来的二进制文件
(2)判断欣赏器有没有msSaveBlob方法,假如有,说用户使用ie欣赏器,直接使用msSaveBlob下载
(3)假如msSaveBlob……(见上图)

注意:msSaveBlob中type的值在打印的res.data中
前端excel、word操作指南

excel

对excel操作所用库

xlsx产物转化表示图

调用blob文件流的方法将blob文件流转换为arrayBuffer,将arrayBuffer给xlsx的read方法,read方法将arrayBuffer读取为一个book对象(可以理解为,将整个excel文件转换为js对象,这个js对象就是book对象),然后从book对象内里提取出对应的sheet对象,接下来就可以将这个sheet对象转换为你想要的前端产物(html或json)了,反过来,也可以把前端的html,一样平常是一个table(一个dom)给过去,转换成一个sheet对象,也可以将前端的json对象转换为sheet对象,然后输出一个excel文件。可以创建一个新的workbook对象,把sheet对象加入到这个新的workbook对象中,然后输出为excel文件
  1. <template>
  2.   <div class="home">
  3.     <!-- 如果是react,则使用该组件
  4.     <fileviews fileType="指定预览的文件类型" fielPath="路径"></fileviews>
  5.     -->
  6.     <!--直接给vueofficeExcel组件的src指定地址即可实现预览,可以给1,线上的路径地址  2,dataURL->base64(将二进制流转换成base64) -->
  7.     <vueofficeExcel v-if="excelSrc" :src="excelSrc" style="height:500px"></vueofficeExcel>
  8.     <button @click="createExcel">创建</button>
  9.     <input type="file" @change="change" />
  10.     <button @click="loadExcel">加载</button>
  11.     <div class="excel-content" v-html="excelHTML"></div>
  12.     <table ref="excelTable">
  13.       <thead>
  14.         <tr>
  15.           <td>科目</td>
  16.           <td>人数</td>
  17.           <td>平均分</td>
  18.         </tr>
  19.       </thead>
  20.       <tr>
  21.         <td rowspan="3">数学</td>
  22.         <td>90</td>
  23.         <td>86</td>
  24.       </tr>
  25.       <tr>
  26.         <td>85</td>
  27.         <td>82</td>
  28.       </tr>
  29.       <tr>
  30.         <td>78</td>
  31.         <td>32</td>
  32.       </tr>
  33.     </table>
  34.   </div>
  35. </template>
  36. <script>
  37. //1,本地选择-》读取为前端html和数据对象
  38. //2,请求-》读取为前端html和数据对象
  39. //1,把前端的一个table dom转化为excel
  40. //2,把一个前端对象转化为excel
  41. import axios from "axios";
  42. import vueofficeExcel from "@vue-office/excel";// 由于使用xlsx库进行预览时,预览的excel很原生,很丑,需要我们自己写样式,所以可以使用@vue-office/excel组件,他的预览功能和原生excel一样,假如我们在excel中设置了样式,vueofficeExcel也会展示出来
  43. // 与此相似的还有"@vue-office/docx"、"@vue-office/pdf",他们定义了不同的预览方式
  44. // 如果使用的是react框架,则使用react-file-viewer,该组件支持很多种类型的预览,不管是word、excel还是ppt都使用这一个组件进行预览
  45. // 他也是一个组件,引入注册后直接使用
  46. import "@vue-office/excel/lib/index.css"
  47. import { read, writeFile, utils } from "xlsx"// xlsx是函数式编程
  48. export default {
  49.   name: 'Home',
  50.   components: {// 注册
  51.     vueofficeExcel
  52.   },
  53.   data() {
  54.     return {
  55.       excelHTML: "",
  56.       excelSrc: ""
  57.     }
  58.   },
  59.   methods: {
  60.     loadExcel() {
  61.       axios.get("http://localhost:8000/download", { responseType: "blob" }).then((res) => {
  62.         console.log(res.data);
  63.         res.data.arrayBuffer().then((res) => {
  64.           const wb = read(res);
  65.           const sheet1 = wb.Sheets.Sheet1
  66.           const _data = utils.sheet_to_json(sheet1);
  67.           const _html = utils.sheet_to_html(sheet1);
  68.           this.excelHTML = _html
  69.         })
  70.       })
  71.     },
  72.     createExcel() {
  73.       let data = [
  74.         { name: "张三", id: 100, score: 99 },
  75.         { name: "张四", id: 200, score: 99 },
  76.         { name: "张五", id: 300, score: 99 }
  77.       ]
  78.       //转化data数组
  79.       const ws = utils.json_to_sheet(data);// 将前端的数据转换为sheet
  80.       const wb = utils.book_new();// 创建空的excel文件,即book对象
  81.       utils.book_append_sheet(wb, ws, "people");// 将sheet表加入excel(book对象),并给这个sheet表命名为people
  82.       writeFile(wb, "test1.xlsx");// 浏览器下载excel,并将其命名为test1.xlsx
  83.       //转化table dom
  84.       const tableDom = this.$refs.excelTable;// 获取table的dom元素
  85.       const tableWs = utils.table_to_sheet(tableDom);// 将dom元素转换为sheet,也可以用table_to_book()直接将其转换为book,然后使用writeFile
  86.       const wb2 = utils.book_new();// 创建book对象,即excel
  87.       utils.book_append_sheet(wb2, tableWs, "sheet1");// 将sheet表加入excel(book对象),并给这个sheet表命名为sheet1
  88.       writeFile(wb2, "tableTest.xlsx");// 浏览器下载excel,并将其命名为tableTest.xlsx
  89.       //const wb2=utils.table_to_book(tableDom);
  90.     },
  91.     change(e) {
  92.       let _file = e.target.files[0]// e.target.files[0]拿到的就是blob文件流
  93.       const fr = new FileReader();// FileReader用于将文件流读取为你想要的格式
  94.       fr.readAsDataURL(_file);// 将文件流读取为base64
  95.       fr.onload = (e) => {
  96.         // 转换完成后获取转换结果
  97.         this.excelSrc = e.target.result;
  98.       }
  99.       /*_file.arrayBuffer().then((res) => {// arrayBuffer()对象本身会返回一个promise
  100.                 // 将blob文件流转换成arrayBuffer,res转换出来的内容
  101.         const wb = read(res);// 读取arrayBuffer,生成一个book对象
  102.         const sheet1 = wb.Sheets.Sheet1// 从Sheets中取出Sheet1这张表
  103.         const _data = utils.sheet_to_json(sheet1);// 将Sheet1表转换为json
  104.         const _html = utils.sheet_to_html(sheet1);// 将Sheet1表转换为html
  105.         this.excelHTML = _html// 需要自己给表格写样式
  106.       })*/
  107.     }
  108.   }
  109. }
  110. </script>
  111. <style>
  112. .excel-content table {
  113.   border-collapse: collapse
  114. }
  115. .excel-content td {
  116.   border: 1px solid black;
  117. }
  118. </style>
复制代码

在做文件预览功能时,都需要提供src路径,这个src要么是线上所在,要么是dataURL,以是一样平常我们都会转换一下路径,假如文件是本地选取的,直接将文件线上所在给src,假如文件是接口返回的,那就是个二进制流,使用FileReader将所在转换为dataURL,再给src
word


  1. <template>
  2.   <div class="home">
  3.     <!--<vueofficedocx v-if="wordPath" :src="wordPath"></vueofficedocx>-->
  4.     <input type="file" @change="change" />
  5.     <div ref="docxPreview"></div>
  6.   </div>
  7. </template>
  8. <script>
  9. import vueofficedocx from "@vue-office/docx";
  10. import { renderAsync } from "docx-preview"
  11. import axios from "axios";
  12. import PizZip from 'pizzip'
  13. import Docxtemplater from 'docxtemplater'// 将word里面的内容作为模版,将html中的数据渲染进去。他接收的的内容是经过压缩的内容,所以还需引入pizzip
  14. import { saveAs } from 'file-saver'// 用于保存文件,你给他一个文件流,他可以把这个文件流作为一个文件导出出来,不仅仅用于word
  15. export default {
  16.   name: 'Home',
  17.   data() {
  18.     return {
  19.       wordPath: ""
  20.     }
  21.   },
  22.   components: {
  23.     vueofficedocx
  24.   },
  25.   methods: {
  26.     change(e) {
  27.       /*let _file = e.target.files[0]
  28.       const fr = new FileReader();
  29.       fr.readAsDataURL(_file);
  30.       fr.onload = (e) => {
  31.         this.wordPath = e.target.result;
  32.       }*/
  33.       //let _file = e.target.files[0];
  34.       //blob,arrayBuffer
  35.       //renderAsync(_file, this.$refs.docxPreview);// renderAsync接收blob/arrayBuffer,并将其渲染到指定dom中进行预览
  36.       let data = {
  37.         student: [
  38.           { name: "张三", id: 100, score: 99 },
  39.           { name: "张四", id: 200, score: 99 },
  40.           { name: "张五", id: 300, score: 99 }
  41.         ]
  42.       }
  43.       let _file = e.target.files[0];
  44.       _file.arrayBuffer().then((res) => {
  45.         let zip = new PizZip(res);// PizZip只能压缩arrayBuffer,所以需要将blob转成arrayBuffer
  46.         const doc = new Docxtemplater(zip);
  47.         doc.setData(data)//设置数据
  48.         doc.render();// 渲染
  49.         const out = doc.getZip().generate({
  50.           type: "blob",
  51.           mimeType:
  52.             "application/vnd.openxmlformats-officedocument.wordprocessingml.document"// 指定word文档的类型
  53.         })// 渲染完成的二进制流
  54.         saveAs(out, "test1.docx")// 保存二进制流并将其命名为test1.docx
  55.       })
  56.     }
  57.   }
  58. }
  59. </script>
  60. <style>
  61. .excel-content table {
  62.   border-collapse: collapse
  63. }
  64. .excel-content td {
  65.   border: 1px solid black;
  66. }
  67. </style>
复制代码
word模版中的内容:


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4