Java实现在线编辑预览office文档

news2024/9/22 1:23:33

文章目录

  • 1 在线编辑
    • 1.1 PageOffice简介
    • 1.2 前端项目
      • 1.2.1 配置
      • 1.2.2 页面部分
    • 1.3 后端项目
      • 1.3.1 pom.xml
      • 1.3.2 添加配置
      • 1.3.3 controller
  • 2 在线预览
    • 2.1 引言
    • 2.2 市面上现有的文件预览服务
      • 2.2.1 微软
      • 2.2.2 Google Drive查看器
      • 2.2.3 阿里云 IMM
      • 2.2.4 XDOC 文档预览
      • 2.2.5 Office Web 365
      • 2.2.6 WPS开放平台
    • 2.3 前端处理方案
      • 2.3.1 pptx的预览方案
      • 2.3.2 pdf的预览方案
        • 2.3.2.1 iframe和embed
        • 2.3.2.2 pdfjs
      • 2.3.3 docx的预览方案
      • 2.3.4 前端预览方案总结
    • 2.4 服务端预览方案
      • 2.4.1 openOffice
      • 2.4.2 kkFileView
      • 2.4.3 onlyOffice

1 在线编辑

1.1 PageOffice简介

PageOffice是一款在线的office编辑软件,帮助Web应用系统或Web网站实现用户在线编辑Word、Excel、PowerPoint文档。可以完美实现在线公文流转,领导批阅,盖章。可以给文件添加水印,在线安全预览防止用户下载和复制文件等

1.2 前端项目

由于pageoffice浏览器是ie内核,vue3不兼容ie。所以需要把页面放在后端

1.2.1 配置

vue.config.js 中配置代理

devServer: {
        proxy: {
        '/api': {
          target: 'http://localhost:8081/samples-springboot-back', //"/api"对应后端项目"http://localhost:8081/samples-springboot-back"地址 
          ws: true,
          changeOrigin: true, // 允许跨域
          pathRewrite: {
           '^/api': ''   // 标识替换,使用 '/api' 代替真实的接口地址
          }
        }
      }
    }

1.2.2 页面部分

index.html页面引用后端项目(samples-springboot-back)根目录下的pageoffice.js

<script type="text/javascript" src="http://localhost:8081/samples-springboot-back/pageoffice.js"></script>

index.vue页面添加一个按钮,调用POBrowser.openWindowModeless请求后端。http://localhost:8081/springboot-pageoffice-demo/SimpleWord/Word2 是后端打开文件的controller

POBrowser.openWindowModeless('http://localhost:8081/springboot-pageoffice-demo/SimpleWord/Word2', 'width=1150px;height=900px;');

在Word.vue页面created中通过axios请求后台获取pageoffice控件(注意:后台返回string字符串,前端需要使用v-html解析)

这里给后台发请求的是axios,如果需要添加token可以在main.js中配置拦截器给请求添加token

Word.vue页面,可以直接复制后修改url

<template>
 <div class="Word">
  <div style="height: 800px; width: auto" v-html="poHtmlCode" />
 </div>
</template>
<script>
const axios = require("axios");
export default {
  name: "Word",
  data() {
    return {
      poHtmlCode: "",
    };
  },
  created: function () {
    axios
      .post("/api/SimpleWord/Word")
      .then((response) => {
        this.poHtmlCode = response.data;
      })
      .catch(function (err) {
        console.log(err);
      });
  },
  methods: {
    //控件中的一些常用方法都在这里调用,比如保存,打印等等
    /**
     * Save()方法是/api/SimpleWord/Word这个后台controller中PageOfficeCtrl控件通过poCtrl.addCustomToolButton定义的方法,除了保存还有另存到本地、打印等功能。
     */
    Save() {
      document.getElementById("PageOfficeCtrl1").WebSave();
    }
  },
  mounted: function () {
    // 将PageOffice控件中的方法通过mounted挂载到window对象上,只有挂载后才能被vue组件识别
    window.Save = this.Save;
  },
};
</script>

1.3 后端项目

1.3.1 pom.xml

<dependency>
    <groupId>com.zhuozhengsoft</groupId>
    <artifactId>pageoffice</artifactId>
    <version>5.4.0.3</version>
</dependency>

1.3.2 添加配置

在启动类中配置servlet beanpoSysPath 是在 properites 中配置的磁盘路径(注意pageofficeposerver.zz等这些请求不要拦截,get和post请求都放出来)

@Bean
public ServletRegistrationBean pageofficeRegistrationBean() {
    com.zhuozhengsoft.pageoffice.poserver.Server poserver = new com.zhuozhengsoft.pageoffice.poserver.Server();
    poserver.setSysPath(poSysPath);//设置PageOffice注册成功后,license.lic文件存放的目录
    ServletRegistrationBean srb = new ServletRegistrationBean(poserver);
    srb.addUrlMappings("/poserver.zz");
    srb.addUrlMappings("/posetup.exe");
    srb.addUrlMappings("/pageoffice.js");
    srb.addUrlMappings("/jquery.min.js");
    srb.addUrlMappings("/pobstyle.css");
    srb.addUrlMappings("/sealsetup.exe");
    return srb;
}

1.3.3 controller

打开文件的controller(webopen第一个参数是当前文件的磁盘路径,磁盘路径必须反向双斜杠)。

setServerPagesetSaveFilePage中的api是前端代理,前后端分离项目必须配置代理

@RestController
@RequestMapping(value = "/SimpleWord")
public class SimpleWordController { 
        @RequestMapping(value="/Word")
        public String showWord(HttpServletRequest request) {
 
            PageOfficeCtrl poCtrl = new PageOfficeCtrl(request);
            poCtrl.setServerPage("/api/poserver.zz");//设置服务页面
            poCtrl.addCustomToolButton("保存", "Save", 1);
 
            poCtrl.setSaveFilePage("/api/SimpleWord/save");//设置保存方法的url
            //打开word
            poCtrl.webOpen("D:\\doc\\test.docx", OpenModeType.docNormalEdit, "张三");
            return  poCtrl.getHtmlCode("PageOfficeCtrl1");
        }
 
        @RequestMapping("save")
        public void save(HttpServletRequest request, HttpServletResponse response) { 
            FileSaver fs = new FileSaver(request, response);
            fs.saveToFile("D:\\doc\\" + fs.getFileName());
            fs.close();
        } 
    }

2 在线预览

2.1 引言

最近遇到了文件预览的需求,但一搜索发现,这还不是一个简单的功能。于是又去查询了很多资料,调研了一些方案,也踩了好多坑。最后总结方案如下:

  • 花钱解决(使用市面上现有的文件预览服务)
    微软,google,阿里云 IMM,XDOC,Office Web 365,wps开放平台
  • 前端方案
    pptx的预览方案,pdf的预览方案,docx的预览方案,xlsx(excel)的预览方案
  • 服务端方案
    openOffice,kkFileView,onlyOffice

2.2 市面上现有的文件预览服务

2.2.1 微软

docx,pptx,xlsx可以说是office三件套,那自然得看一下微软官方提供的文件预览服务。使用方法特别简单,只需要将文件链接,拼接到参数后面即可。
记得encodeURL
https://view.officeapps.live.com/op/view.aspx?src=${encodeURIComponent(url)}

对于docx,pptx,xlsx都有较好的支持,pdf不行。
还有一个坑点是:这个服务是否稳定,有什么限制,是否收费,都查不到一个定论。在office官方网站上甚至找不到介绍这个东西的地方。

目前只能找到一个Q&A:answers.microsoft.com/en-us/msoff…[1]

微软官方人员回答表示:

图片
翻译翻译,就是:几乎永久使用,没有收费计划,不会存储预览的文件数据,限制文件10MB,建议用于 查看互联网上公开的文件。
但经过某些用户测试发现,使用了微软的文件预览服务,然后删除了文件地址,仍然可访问,但过一段时间才会失效。

2.2.2 Google Drive查看器

接入简单,同 Office Web Viewer,只需要把 src 改为https://drive.google.com/viewer?url=${encodeURIComponent(url)}即可。

限制25MB,支持以下格式:
在这里插入图片描述

测试效果,支持docx,pptx,xlsx,pdf预览,但pptx预览的效果不如微软,没有动画效果,样式有小部分会错乱。

2.2.3 阿里云 IMM

官方文档如下:https://help.aliyun.com/zh/imm/?spm=5176.28426678.J_HeJR_wZokYt378dwP-lLl.1.59575181eAvyQZ&scm=20140722.S_help@@文档@@62354.S_BB1@bl+BB2@bl+RQW@ag0+hot+os0.ID_62354-RL_智能媒体管理-LOC_search~UND~helpdoc~UND~item-OR_ser-V_3-P0_0
在这里插入图片描述
付费使用

2.2.4 XDOC 文档预览

说了一些大厂的,在介绍一些其他的,需要自行分辨
官网地址:view.xdocin.com/view-xdocin…[3]
在这里插入图片描述

2.2.5 Office Web 365

需要注意的是,虽然名字很像office,但我们看网页的Copyright可以发现,其实是一个西安的公司,不是微软,但毕竟也提供了文件预览的服务
官网地址:www.officeweb365.com/[4]
在这里插入图片描述

2.2.6 WPS开放平台

官方地址:solution.wps.cn/[5]
在这里插入图片描述
付费使用,价格如下:
在这里插入图片描述

2.3 前端处理方案

2.3.1 pptx的预览方案

先查一下有没有现成的轮子,目前 pptx 的开源预览方案能找到的只有这个:github.com/g21589/PPTX…[6] 。但已经六七年没有更新,也没有维护,笔者使用的时候发现有很多兼容性问题。
简单来说就是,没有。
对于这种情况,我们可以自行解析,主要步骤如下:

  • 查询pptx的国际标准
  • 解析pptx文件
  • 渲染成html或者canvas进行展示

我们先去找一下pptx的国际标准,官方地址:officeopenxml[7]
先解释下什么是officeopenxml:

Office OpenXML,也称为OpenXMLOOXML,是一种基于XML的办公文档格式,包括文字处理文档、电子表格、演示文稿以及图表、图表、形状和其他图形材料。该规范由微软开发,并于2006年被ECMA国际采用为ECMA-376。第二个版本于2008年12月发布,第三个版本于2011年6月发布。该规范已被ISO和IEC采用为ISO/IEC 29500。
虽然Microsoft继续支持较旧的二进制格式(.doc、.xls和.ppt),但OOXML现在是所有Microsoft Office文档(.docx、.xlsx和.pptx)的默认格式。
由此可见,Office OpenXML由微软开发,目前已经是国际标准。

接下来我们看一下pptx里面有哪些内容,具体可以看pptx的官方标准:officeopenxml-pptx[8]

PresentationML或.pptx文件是一个zip文件,其中包含许多“部分”(通常是UTF-8或UTF-16编码)或XML文件。该包还可能包含其他媒体文件,例如图像。该结构根据 OOXML 标准 ECMA-376 第 2 部分中概述的开放打包约定进行组织。

根据国际标准,我们知道,pptx文件本质就是一个zip文件,其中包含许多部分:

部件的数量和类型将根据演示文稿中的内容而有所不同,但始终会有一个 [Content_Types].xml、一个或多个关系 (.rels) 部件和一个演示文稿部件(演示文稿.xml),它位于 ppt 文件夹中,用于Microsoft Powerpoint 文件。通常,还将至少有一个幻灯片部件,以及一张母版幻灯片和一张版式幻灯片,从中形成幻灯片。

那么js如何读取zip呢?

找到一个工具: www.npmjs.com/package/jsz…[9]

于是我们可以开始尝试解析pptx了。

import JSZip from 'jszip'
// 加载pptx数据
const zip = await JSZip.loadAsync(pptxData)

解析[Content_Types].xml
每个pptx必然会有一个 [Content_Types].xml。此文件包含包中部件的所有内容类型的列表。每个部件及其类型都必须列在 [Content_Types].xml 中。通过它里面的内容,可以解析其他的文件数据

const filesInfo = await getContentTypes(zip)

async function getContentTypes(zip: JSZip) {
    const ContentTypesJson = await readXmlFile(zip, '[Content_Types].xml')
    const subObj = ContentTypesJson['Types']['Override']
    const slidesLocArray = []
    const slideLayoutsLocArray = []
    for (let i = 0; i < subObj.length; i++) {
      switch (subObj[i]['attrs']['ContentType']) {
        case 'application/vnd.openxmlformats-officedocument.presentationml.slide+xml':
          slidesLocArray.push(subObj[i]['attrs']['PartName'].substr(1))
          break
        case 'application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml':
          slideLayoutsLocArray.push(subObj[i]['attrs']['PartName'].substr(1))
          break
        default:
      }
    }
    return {
      slides: slidesLocArray,
      slideLayouts: slideLayoutsLocArray,
    }
  }

解析演示文稿
先获取ppt目录下的presentation.xml演示文稿的大小
由于演示文稿是xml格式,要真正的读取内容需要执行 readXmlFile

const slideSize = await getSlideSize(zip)
 async function getSlideSize(zip: JSZip) {
    const content = await readXmlFile(zip, 'ppt/presentation.xml')
    const sldSzAttrs = content['p:presentation']['p:sldSz']['attrs']
    return {
      width: (parseInt(sldSzAttrs['cx']) * 96) / 914400,
      height: (parseInt(sldSzAttrs['cy']) * 96) / 914400,
    }
  }

加载主题
根据 officeopenxml的标准解释

每个包都包含一个关系部件,用于定义其他部件之间的关系以及与包外部资源的关系。这样可以将关系与内容分开,并且可以轻松地更改关系,而无需更改引用目标的源。
除了包的关系部分之外,作为一个或多个关系源的每个部件都有自己的关系部分。每个这样的关系部件都可以在部件的_rels子文件夹中找到,并通过在部件名称后附加“.rels”来命名。

其中主题的相关信息就在ppt/_rels/presentation.xml.rels中

  async function loadTheme(zip: JSZip) {
    const preResContent = await readXmlFile(
      zip,
      'ppt/_rels/presentation.xml.rels',
    )
    const relationshipArray = preResContent['Relationships']['Relationship']
    let themeURI
    if (relationshipArray.constructor === Array) {
      for (let i = 0; i < relationshipArray.length; i++) {
        if (
          relationshipArray[i]['attrs']['Type'] ===
          'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme'
        ) {
          themeURI = relationshipArray[i]['attrs']['Target']
          break
        }
      }
    } else if (
      relationshipArray['attrs']['Type'] ===
      'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme'
    ) {
      themeURI = relationshipArray['attrs']['Target']
    }

    if (themeURI === undefined) {
      throw Error("Can't open theme file.")
    }

    return readXmlFile(zip, 'ppt/' + themeURI)
  }

2.3.2 pdf的预览方案

2.3.2.1 iframe和embed

pdf 比较特别,一般的浏览器默认支持预览pdf。因此,我们可以使用浏览器的能力:<iframe src="viewFileUrl" />
但这样就完全依赖浏览器,对PDF的展示,交互,是否支持全看浏览器的能力,且不同的浏览器展示和交互往往不同,如果需要统一的话,最好还是尝试其他方案。
embed的解析方式也是一样,这里不举例子了

2.3.2.2 pdfjs
npm: www.npmjs.com/package/pdf…[12]
github地址:github.com/mozilla/pdf…[13]

由mozilla出品,就是我们常见的MDN的老大。而且目前 火狐浏览器 使用的 PDF 预览就是采用这个,我们可以用火狐浏览器打开pdf文件,查看浏览器使用的js就能发现

需要注意的是,最新版 pdf.js 限制了 node 版本,需要大于等于18
github链接:github.com/mozilla/pdf…

如果你项目node版本小于这个情况,可能会无法使用。

具体使用情况如下:

import * as pdfjs from 'pdfjs-dist'
import * as pdfjsWorker from 'pdfjs-dist/build/pdf.work.entry'

interface Viewport {
  width: number
  height: number
  viewBox: Array<number>
}

interface RenderContext {
  canvasContext: CanvasRenderingContext2D | null
  transform: Array<number>
  viewport: Viewport
}

interface PDFPageProxy {
  pageNumber: number
  getViewport: () => Viewport
  render: (options: RenderContext) => void
}

interface PDFDocumentProxy {
  numPages: number
  getPage: (x: number) => Promise<PDFPageProxy>
}

class PdfPreview {
  private pdfDoc: PDFDocumentProxy | undefined
  pageNumber: number
  total: number
  dom: HTMLElement
  pdf: string | ArrayBuffer
  constructor(pdf: string | ArrayBuffer, dom: HTMLElement | undefined) {
    this.pageNumber = 1
    this.total = 0
    this.pdfDoc = undefined
    this.pdf = pdf
    this.dom = dom ? dom : document.body
  }
  private getPdfPage = (number: number) => {
    return new Promise((resolve, reject) => {
      if (this.pdfDoc) {
        this.pdfDoc.getPage(number).then((page: PDFPageProxy) => {
          const viewport = page.getViewport()
          const canvas = document.createElement('canvas')
          this.dom.appendChild(canvas)
          const context = canvas.getContext('2d')
          const [_, __, width, height] = viewport.viewBox
          canvas.width = width
          canvas.height = height
          viewport.width = width
          viewport.height = height
          canvas.style.width = Math.floor(viewport.width) + 'px'
          canvas.style.height = Math.floor(viewport.height) + 'px'
          const renderContext = {
            canvasContext: context,
            viewport: viewport,
            transform: [1, 0, 0, -1, 0, viewport.height],
          }
          page.render(renderContext)
          resolve({ success: true, data: page })
        })
      } else {
        reject({ success: false, data: null, message: 'pdfDoc is undefined' })
      }
    })
  }
  pdfPreview = () => {
      window.pdfjsLib.GlobalWorkerOptions.workerSrc = pdfjsWorker
      window.pdfjsLib
        .getDocument(this.pdf)
        .promise.then(async (doc: PDFDocumentProxy) => {
          this.pdfDoc = doc
          this.total = doc.numPages
          for (let i = 1; i <= this.total; i++) {
            await this.getPdfPage(i)
          }
    })
  }
  prevPage = () => {
    if (this.pageNumber > 1) {
      this.pageNumber -= 1
    } else {
      this.pageNumber = 1
    }
    this.getPdfPage(this.pageNumber)
  }
  nextPage = () => {
    if (this.pageNumber < this.total) {
      this.pageNumber += 1
    } else {
      this.pageNumber = this.total
    }
    this.getPdfPage(this.pageNumber)
  }
}

const createReader = (file: File): Promise<string | ArrayBuffer | null> => {
  return new Promise((resolve, reject) => {
    const reader = new FileReader()
    reader.readAsDataURL(file)
    reader.onload = () => {
      resolve(reader.result)
    }
    reader.onerror = (error) => {
      reject(error)
    }
    reader.onabort = (abort) => {
      reject(abort)
    }
  })
}

export const renderPdf = async (
  file: File,
  dom?: HTMLElement,
): Promise<void> => {
  try {
    if (typeof window !== 'undefined') {
      const pdf = await createReader(file)
      if (pdf) {
        const PDF = new PdfPreview(pdf, dom)
        PDF.pdfPreview()
      }
    }
  } catch (error) {
    console.log('renderPdf', error)
  }
}

2.3.3 docx的预览方案

我们可以去查看docx的国际标准,去解析文件格式,渲染成htmlcanvas,不过比较好的是,已经有人这么做了,还开源了

使用方法如下:

import { renderAsync } from 'docx-preview'

interface DocxOptions {
  bodyContainer?: HTMLElement | null
  styleContainer?: HTMLElement
  buffer: Blob
  docxOptions?: Partial<Record<string, string | boolean>>
}

export const renderDocx = (options: DocxOptions): Promise<void> | undefined => {
  if (typeof window !== 'undefined') {
    const { bodyContainer, styleContainer, buffer, docxOptions = {} } = options
    const defaultOptions = {
      className: 'docx',
      ignoreLastRenderedPageBreak: false,
    }
    const configuration = Object.assign({}, defaultOptions, docxOptions)
    if (bodyContainer) {
      return renderAsync(buffer, bodyContainer, styleContainer, configuration)
    } else {
      const contain = document.createElement('div')
      document.body.appendChild(contain)
      return renderAsync(buffer, contain, styleContainer, configuration)
    }
  }
}

2.3.4 前端预览方案总结

我们对以上找到的优秀的解决方案,进行改进和总结,并封装成一个web components组件:preview组件

为什么是web components组件?
因为它跟框架无关,可以在任何框架中使用,且使用起来跟原生的div标签一样方便。并编写使用文档: preview组件文档, 文档支持交互体验。

目前docx,pdf,xlsx预览基本可以了,都是最好的方案。pptx预览效果不太好,因为需要自行解析。

2.4 服务端预览方案

2.4.1 openOffice

由于浏览器不能直接打开 docx,pptx,xlsx 等格式文件,但可以直接打开pdf和图片,因此,我们可以换一个思路,用服务端去转换下文件的格式,转换成浏览器能识别的格式,然后再让浏览器打开,这不就OK了吗,甚至不需要前端处理了。
我们可以借助openOffice的能力,先介绍一下openOffice:

Apache OpenOffice是领先的开源办公软件套件,用于文字处理,电子表格,演示文稿,图形,数据库等。它有多种语言版本,适用于所有常用计算机。它以国际开放标准格式存储您的所有数据,还可以从其他常见的办公软件包中读取和写入文件。它可以出于任何目的完全免费下载和使用。
官网如下:www.openoffice.org

完整示例如下:

package org.example;

import org.artofsolving.jodconverter.OfficeDocumentConverter;
import org.artofsolving.jodconverter.office.DefaultOfficeManagerConfiguration;
import org.artofsolving.jodconverter.office.OfficeManager;

import java.io.File;

public class OfficeUtil {

    private static OfficeManager officeManager;
    private static int port[] = {8100};

    /**
     * start openOffice service.
     */
    public static void startService() {
        DefaultOfficeManagerConfiguration configuration = new DefaultOfficeManagerConfiguration();
        try {
            System.out.println("准备启动office转换服务....");
            configuration.setOfficeHome("这里的路径一般为C:\\Program Files (x86)\\OpenOffice 4的bin目录");
            configuration.setPortNumbers(port); // 设置转换端口,默认为8100
            configuration.setTaskExecutionTimeout(1000 * 60 * 30L);// 设置任务执行超时为30分钟
            configuration.setTaskQueueTimeout(1000 * 60 * 60 * 24L);// 设置任务队列超时为24小时
            officeManager = configuration.buildOfficeManager();
            officeManager.start(); // 启动服务
            System.out.println("office转换服务启动成功!");
        } catch (Exception e) {
            System.out.println("office转换服务启动失败!详细信息:" + e);
        }
    }

    /**
     * stop openOffice service.
     */
    public static void stopService() {
        System.out.println("准备关闭office转换服务....");
        if (officeManager != null) {
            officeManager.stop();
        }
        System.out.println("office转换服务关闭成功!");
    }

    public static void convertToPDF(String inputFile, String outputFile) {
        startService();
        System.out.println("进行文档转换转换:" + inputFile + " --> " + outputFile);
        OfficeDocumentConverter converter = new OfficeDocumentConverter(officeManager);
        converter.convert(new File(inputFile), new File(outputFile));
        stopService();
    }

    public static void main(String[] args) {
        convertToPDF("/Users/koolearn/Desktop/asdf.docx", "/Users/koolearn/Desktop/adsf.pdf");
    }
}

2.4.2 kkFileView

支持的文件预览格式非常丰富图片
在这里插入图片描述
安装下libreoffice :
kkFileView明确要求的额外依赖 libreoffice,否则无法启动

启动项目
找到主文件,主函数mian,即可执行

2.4.3 onlyOffice

官网地址:https://www.onlyoffice.com/zh
开发者版本和社区版免费,企业版付费:www.onlyoffice.com/zh/docs-ent

预览的文件种类没有kkFileView多,但对office三件套有很好的支持,甚至支持多人编辑。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1381466.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

逆变器3前级推免(高频变压器)

一节电池标压是在2.8V—4.2V之间&#xff0c;所以24V电压需要大概七节电池串联。七节电池电压大概在19.6V—29.4V之间。 从24V的电池逆变到到220V需要升压的过程。那么我们具体需要升压到多少&#xff1f; 市电AC220V是有效值电压&#xff0c;峰值电压是220V*1.414311V 如果…

ubuntu安装node

1 下载 node 官网下载 如果需要其他版本&#xff0c;点击上图的Other Downloads 这里下载的版本是20.11.0 Linux Binaries (x64)&#xff0c;下载下来后是node-v20.11.0-linux-x64.tar.xz这样的格式&#xff0c;直接右键解压得到如下目录&#xff1a; 直接拷贝该文件夹到指定目…

一些前端学习过程的自测练习题

目录 页面设计部分 1 设计一个简单的学院网站首页&#xff1b; 2.按照图示要求完成简单的登录页面 3.完成如下网站设计 4.完成如下网站设计&#xff08;练习页面布局&#xff09; 5 利用下面素材&#xff0c;设计一个满足H5规范的网页&#xff08;移动端页面练习&#xff…

有道云笔记编辑 Markdown 文件 - GitHub README.md

有道云笔记编辑 Markdown 文件 - GitHub README.md 1. 新建 -> Markdown2. GitHub README.mdReferences 1. 新建 -> Markdown ​ 2. GitHub README.md ​​​ References [1] Yongqiang Cheng, https://yongqiang.blog.csdn.net/

group by 查询慢的话,如何优化?

1、说明 根据一定的规则&#xff0c;进行分组。 group by可能会慢在哪里&#xff1f;因为它既用到临时表&#xff0c;又默认用到排序。有时候还可能用到磁盘临时表。 如果执行过程中&#xff0c;会发现内存临时表大小到达了上限&#xff08;控制这个上限的参数就是tmp_table…

中通快递批量查询方法

你是否经常需要处理大量的中通快递单号&#xff0c;却苦于一个个等待查询&#xff1f;现在&#xff0c;有了固乔快递查询助手&#xff0c;这个问题迎刃而解&#xff01;通过批量查询功能&#xff0c;你可以轻松管理、追踪你的中通快递单号&#xff0c;大大提高工作效率。 一、下…

spark中Rdd依赖和SparkSQL介绍--学习笔记

1&#xff0c;RDD的依赖 1.1概念 rdd的特性之一 相邻rdd之间存在依赖关系&#xff08;因果关系&#xff09; 窄依赖 每个父RDD的一个Partition最多被子RDD的一个Partition所使用 父rdd和子rdd的分区是一对一&#xff08;多对一&#xff09; 触发窄依赖的算子 map()&…

提交代码,SVN被锁定,提示:svn is already locked解决方案

今天遇到一个问题&#xff0c;svn 在提交代码的时候出现了svn is already locked&#xff0c;解决方案如下图 点击clean up 点击ok即可 来看官方对clean up的解释&#xff1a;它的作用就是查找工作拷贝中的所有遗留的日志文件&#xff0c;删除进程中工作拷贝的锁。 参考&…

掌握 Vue 响应式系统,让数据驱动视图(上)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

【MATLAB源码-第109期】基于matlab的哈里斯鹰优化算发(HHO)机器人栅格路径规划,输出做短路径图和适应度曲线。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 哈里斯鹰优化算法&#xff08;Harris Hawk Optimization, HHO&#xff09;是一种受自然界捕食行为启发的优化算法。它基于哈里斯鹰的捕猎策略和行为模式&#xff0c;主要用于解决各种复杂的优化问题。这个算法的核心特征在于…

RuoYi-Vue-Plus 5.X登录前流程及解密

一&#xff1a;问题 1. 前端传给后端的是一个加密字符串&#xff0c;后端controller层login接口怎么就直接解密了呢&#xff1f; 2. 中间经过什么步骤到达的登录接口呢&#xff1f; 二&#xff1a;个人分析 首先考虑的是拦截器、过滤器、切面AOP&#xff1b; 1. 使用全文搜…

轻松查看WiFi密码的神奇脚本,让你忘记密码也不再是问题

说在前面 &#x1f388;本文介绍了一个便捷的脚本&#xff0c;可以帮助你获取电脑中保存的所有Wi-Fi网络的密码。不再需要担心忘记Wi-Fi密码或手动查找密码的麻烦&#xff0c;只需运行脚本即可一键获取。 一、引言 互联网的普及让我们离不开Wi-Fi网络&#xff0c;但忘记密码时…

如何有效提高矢量网络分析仪的动态范围

动态范围是网络分析仪&#xff08;VNA&#xff09;接收机的最大输入功率与最小可测量功率&#xff08;本底噪声&#xff09;之间的差值&#xff0c;如图所示&#xff0c;要使测量有效&#xff0c;输入信号必须在这些边界内。 如果需要测量信号幅度非常大的变化&#xff0c;例如…

ISO11898-闭环高速CAN网络 (125K~1Mbps)

ISO11898 标准的物理框图如下图 可理解为一个高速闭环 CAN 总线网络&#xff1b;CAN 闭环总线网络允许总线最大长度为 40m;最高速度为 1Mbps;可以看到总线的两端各有一个 120Ω 的电阻&#xff0c;此电阻作为阻抗匹配功能&#xff0c;以减少回波反射;节点就是不同的设备&#…

蓝桥杯单片机组备赛——数码管动态显示

✨文章内容会不断优化&#xff0c;如果你感兴趣的话&#xff0c;欢迎点藏收藏关注我哟 &#x1f9e8;如果文章有哪里看不懂的欢迎评论区或私信留言&#xff0c;我会及时回复的 ⏰如果文章出现错误&#xff0c;欢迎指正&#xff0c;看到后我会马上改正 文章目录 一、动态显示原理…

调用openai实现聊天功能

&#x1f4d1;前言 本文主要是【聊天机器人】——调用openai实现聊天功能的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 &#x1f3…

【面试突击】分布式锁、幂等性问题实战

&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308; 欢迎关注公众号&#xff08;通过文章导读关注&#xff1a;【11来了】&#xff09;&#xff0c;及时收到 AI 前沿项目工具及新技术 的推送 发送 资料 可领取 深入理…

计算机体系结构----存储系统

本文严禁转载&#xff0c;仅供学习使用。参考资料来自中国科学院大学计算机体系结构课程PPT以及《Digital Design and Computer Architecture》、《超标量处理器设计》、同济大学张晨曦教授资料。如有侵权&#xff0c;联系本人修改。 1.1 引言 1.1.1虚拟和物理内存 程序员看到…

ORA-12541:TNS:无监听程序

1.重新配置监听 找到监听程序配置&#xff0c;右键已管理员身份运行 选择第二个&#xff1a;重新配置 这个一般没什么好选的 默认选定的协议TCP&#xff0c;继续下一步 默认的否 继续下一步&#xff0c;完成监听重新配置 之后进行测试看能否连上 2.本地Net服务名配置 …

2024年前端最新面试题-vue3(持续更新中)

文章目录 前言正文什么是 MVVC什么是 MVVM什么是 SPA什么是SFC为什么 data 选项是一个函数Vue 组件通讯&#xff08;传值&#xff09;有哪些方式Vue 的生命周期方法有哪些如何理解 Vue 的单项数据流如何理解 Vue 的双向数据绑定Vue3的响应式原理是什么介绍一下 Vue 的虚拟 DOM介…