本帖最后由 ann 于 2022-8-25 12:04 编辑
日常向开发中,如果是前后端分离的项目,同时涉及到文件的操作,难免存在文件传输的需求,本质上是对文件流的传输和解析,下面我们通过代码实战来直观感受下。
一、前端同步文件到后端SpreadJs在保存文件时,借助GC.Spread.Excel.IO组件的save方法,可以获取到文件的blob对象。因此在前端项目中可通过调用save方法,获取到blob对象,然后重写自己的文件传输逻辑。
SpreadJs导入导出Excel官网实例:https://demo.grapecity.com.cn/sp ... mport-export/purejs
Blob对象简介:BLOB 简介
1.1 前端实现-React前端借助SpreadJs的在线表格编辑器,导入本地Excel文件,借助excelIo.save方法获取到文件的Blob对象,然后以表单的方式提交请求到后端。
前端代码
- import React from 'react'
- import {Button, Col, message, Space, Switch} from "antd";
- import '@grapecity/spread-sheets-resources-zh';
- import '@grapecity/spread-sheets-designer-resources-cn';
- import {Designer} from '@grapecity/spread-sheets-designer-react';
- import GC from "@grapecity/spread-sheets";
- import * as ExcelIo from "@grapecity/spread-excelio"
- GC.Spread.Common.CultureManager.culture("zh-cn");
- const config = GC.Spread.Sheets.Designer.DefaultConfig
- export default class SpreadJs extends React.Component {
- constructor(props) {
- super(props);
- this.designer = null
- this.state = {
- spread: null,
- }
- }
- componentDidMount() {
- }
- onClick = () => {
- let spread = this.state.spread;
- let json = spread.toJSON();
- this.excelIo = new ExcelIo.IO();
- this.excelIo.save(json, function (blob) {
- let formData = new FormData();
- formData.append("content", blob,"111.xlsx");
- let request = new XMLHttpRequest();
- request.open("POST", "http://localhost:8080/send/file/blob",)
- request.send(formData)
- }, function (e) {
- console.log(e);
- });
- //也可直接将string对象转换为Blob然后传输到后端
- //let blob=new Blob([JSON.stringfy(spread.toJSON())],{type:"application/json"})
- }
- /**
- * 初始化spread
- * @param designer
- */
- designerInitialized = (designer) => {
- this.designer = designer;
- let spread = this.designer.getWorkbook()
- this.setState({spread})
- }
- render() {
- return (
- <div>
- <Col>
- <Button type='primary' onClick={this.onClick}
- style={{backgroundColor: '#22e7ff', marginLeft: 20, marginTop: 5}}>向后端传输文件</Button>
- </Col>
- <Designer
- spreadOptions={{sheetCount: 1}}
- styleInfo={{width: "100%", height: '80vh'}}
- config={config}
- designerInitialized={this.designerInitialized}
- ></Designer>
- </div>
- )
- }
- }
复制代码 1.2 后端实现-JAVA- @RequestMapping(value = "/send/file/blob", produces = {"application/json;charset=utf-8"})
- public void sendFileBlob(HttpServletResponse response, HttpServletRequest request) {
- MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
- Iterator<String> iter = multiRequest.getFileNames();
- while (iter.hasNext()) {
- MultipartFile multipartFile = multiRequest.getFile(iter.next());
- if (null != multipartFile) {
- String fileName = multipartFile.getOriginalFilename();
- if (fileName == null || fileName.trim().equals("")) {
- continue;
- }
- //todo 具体的业务逻辑
- }
- }
- }
复制代码 1.3 效果演示
借助SpreadJs的在线表格编辑器,导入本地文档111.xlsx。
点击“向后端传输文件”按钮,触发文件传输,后端可获取到对应的文件信息。可做具体的业务逻辑。
二、后端同步文件到前端
从后端后获取文件流同步到前端,然后直接在浏览器中下载
2.1 前端实现-React- //加载指定的文件流到前端浏览器下载
- loadFile = () => {
- let filePath = "/Users/yak/myProject/exceldemo/tttt3.xlsx";
- return new Promise((resolve, reject) => {
- axios({
- method: 'get',
- url: "http://localhost:8080/upload/file?filePath=" + filePath,
- responseType: 'blob'
- }).then(data => {
- let blob = data.data;
- const link = document.createElement("a");
- link.href = URL.createObjectURL(blob);
- link.download = "text.xlsx";
- link.click();
- link.remove();
- URL.revokeObjectURL(link.href);}).catch(error => {
- reject(error.toString())
- })
- })
- }
复制代码 2.2 后端实现-JAVA
读取本地文件,将其转换为二进制字节流,提供接口给第三方访问。
- @GetMapping(value = "/upload/file")
- public void download(String filePath, HttpServletResponse response) throws Exception {
- ServletOutputStream out = null;
- ByteArrayOutputStream byteArrayOutputStream = null;
- try {
- FileInputStream inputStream = new FileInputStream(filePath);
- String[] filePaths = StringUtil.split(filePath,"/");
- byte[] buffer = new byte[1024];
- int len;
- byteArrayOutputStream = new ByteArrayOutputStream();
- while ((len = inputStream.read(buffer)) != -1) {
- byteArrayOutputStream.write(buffer, 0, len);
- }
- response.addHeader("Content-Disposition", "attachment;filename=" + filePaths[filePaths.length-1]);
- response.addHeader("Content-Length", "" + byteArrayOutputStream.size());
- response.setHeader("filename", filePaths[filePaths.length-1]);
- response.setContentType("application/octet-stream");
- out = response.getOutputStream();
- out.write(byteArrayOutputStream.toByteArray());
- } catch (Exception e) {
- e.printStackTrace();
- throw new RuntimeException();
- } finally {
- // 关闭文件流
- if (null != byteArrayOutputStream) {
- byteArrayOutputStream.flush();
- byteArrayOutputStream.close();
- }
- if (null != out) {
- out.flush();
- out.close();
- }
- }
- }
复制代码 2.3 效果演示
前端获取到后端同步的文件流对象
浏览器侧的下载实现
|
|