扫码关注
「
后端架构师
」,选择
「
星标
」
公众号
重磅干货,第一时间送达!
责编:架构君 | 来源:然燃
链接:juejin.cn/post/7268530145208451124
上一篇好文:
大家好,我是后端架构师。
最近遇到了文件预览的需求,但一搜索发现,这还不是一个简单的功能。于是又去查询了很多资料,调研了一些方案,也踩了好多坑。最后总结方案如下
花钱解决(使用市面上现有的文件预览服务)
微软
google
阿里云 IMM
XDOC
Office Web 365
wps开放平台
前端方案
pptx的预览方案
pdf的预览方案
docx的预览方案
xlsx(excel)的预览方案
前端预览方案总结
服务端方案
openOffice
kkFileView
onlyOffice
如果有其他人也遇到了同样的问题,有了这篇文章,希望能更方便的解决。
基本涵盖了所有解决方案。因此,标题写上 最全 的文件预览方案调研总结,应该不为过吧。
1 市面上现有的文件预览服务
1.微软
docx
,
pptx
,
xlsx
可以说是
office
三件套,那自然得看一下
微软官方
提供的文件预览服务。使用方法特别简单,只需要将文件链接,拼接到参数后面即可。
记得
encodeURL
https://view.officeapps.live.com/op/view.aspx?src=${encodeURIComponent(url)}
(1).PPTX预览效果:
优点:还原度很高,功能很丰富,可以选择翻页,甚至支持点击播放动画。
缺点:不知道是不是墙的原因,加载稍慢。
(2).Excel预览效果:
(3).Doxc预览效果
(4).PDF预览效果
这个我测试没有成功,返回了一个错误,其他人可以试试。
(5).总的来说
对于
docx
,
pptx
,
xlsx
都有较好的支持,
pdf
不行。
还有一个坑点是:这个服务是否稳定,有什么限制,是否收费,都查不到一个定论。在
office
官方网站上甚至找不到介绍这个东西的地方。
目前只能找到一个
Q&A
:
answers.microsoft.com/en-us/msoff…
[1]
微软官方人员回答表示:
翻译翻译,就是:几乎永久使用,没有收费计划,不会存储预览的文件数据,限制文件
10MB
,建议用于
查看互联网上公开的文件
。
但经过某些用户测试发现:
使用了微软的文件预览服务,然后删除了文件地址,仍然可访问,但过一段时间会失效。
2.Google Drive 查看器
接入简单,同
Office Web Viewer
,只需要把
src
改为
https://drive.google.com/viewer?url=${encodeURIComponent(url)}
即可。
限制
25MB
,支持以下格式:
测试效果,支持
docx,pptx,xlsx,pdf
预览,但
pptx
预览的效果不如微软,没有动画效果,样式有小部分会错乱。
由于某些众所周知的原因,不可用
3.阿里云 IMM
官方文档如下: help.aliyun.com/document_de… [2]
付费使用
4.XDOC 文档预览
说了一些大厂的,在介绍一些其他的, 需要自行分辨
官网地址: view.xdocin.com/view-xdocin… [3]
5.Office Web 365
需要注意的是,虽然名字很像
office
,但我们看网页的
Copyright
可以发现,其实是一个西安的公司,
不是微软
。
但毕竟也提供了文件预览的服务
官网地址: www.officeweb365.com/ [4]
6.WPS开放平台
官方地址: solution.wps.cn/ [5]
付费使用,价格如下:
2 前端处理方案
1.pptx的预览方案
先查一下有没有现成的轮子,目前
pptx
的开源预览方案能找到的只有这个:
github.com/g21589/PPTX…
[6]
。但已经六七年没有更新,也没有维护,笔者使用的时候发现有很多兼容性问题。
简单来说就是,没有。对于这种情况,我们可以自行解析,主要步骤如下:
查询
pptx
的国际标准解析
pptx
文件渲染成
html
或者canvas
进行展示
我们先去找一下
pptx
的国际标准,官方地址:
officeopenxml
[7]
先解释下什么是
officeopenxml
:
Office OpenXML,也称为OpenXML或OOXML,是一种基于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)asyncfunctiongetContentTypes(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)) breakcase'application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml': slideLayoutsLocArray.push(subObj[i]['attrs']['PartName'].substr(1)) breakdefault: } } return { slides: slidesLocArray, slideLayouts: slideLayoutsLocArray, } }
解析演示文稿
先获取
ppt
目录下的
presentation.xml
演示文稿的大小
由于演示文稿是
xml
格式,要真正的读取内容需要执行
readXmlFile
const slideSize = await getSlideSize(zip) asyncfunctiongetSlideSize(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
中
asyncfunctionloadTheme(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 } } } elseif ( relationshipArray['attrs']['Type'] === 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme' ) { themeURI = relationshipArray['attrs']['Target'] } if (themeURI === undefined) { throwError("Can't open theme file.") } return readXmlFile(zip, 'ppt/' + themeURI) }
后续
ppt
里面的其他内容,都可以这么去解析。根据
officeopenxml
标准,可能包含:
等等内容,我们根据标准一点点解析并渲染就好了。
完整源码: ranui [10]
使用文档: preview组件 [11]
2.pdf的预览方案
(1).iframe和embed
pdf
比较特别,一般的浏览器默认支持预览
pdf
。因此,我们可以使用浏览器的能力:
<iframe src="viewFileUrl" />
但这样就完全依赖浏览器,对
PDF
的展示,交互,是否支持全看浏览器的能力,且不同的浏览器展示和交互往往不同,如果需要统一的话,最好还是尝试其他方案。
embed
的解析方式也是一样,这里不举例子了
(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… [14]
如果你项目
node
版本小于这个情况,可能会无法使用。
具体使用情况如下:
完整源码: github.com/chaxus/ran/… [15]
使用文档: chaxus.github.io/ran/src/ran… [16]
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 | ArrayBufferconstructor(pdf: string | ArrayBuffer, dom: HTMLElement | undefined) { this.pageNumber = 1this.total = 0this.pdfDoc = undefinedthis.pdf = pdf this.dom = dom ? dom : document.body } private getPdfPage = (number: number) => { returnnewPromise((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++) { awaitthis.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> => { returnnewPromise((resolve, reject) => { const reader = new FileReader() reader.readAsDataURL(file) reader.onload = () => { resolve(reader.result) } reader.onerror = (error) => { reject(error) } reader.onabort = (abort) => { reject(abort) } })}exportconst renderPdf = async ( file: File, dom?: HTMLElement,): Promise<void> => { try { if (typeofwindow !== 'undefined') { const pdf = await createReader(file) if (pdf) { const PDF = new PdfPreview(pdf, dom) PDF.pdfPreview() } } } catch (error) { console.log('renderPdf', error) }}
3.docx的预览方案
我们可以去查看
docx
的国际标准,去解析文件格式,渲染成
html
和
canvas
,不过比较好的是,已经有人这么做了,还开源了
npm
地址:
www.npmjs.com/package/doc…
[17]
使用方法如下:
import { renderAsync } from'docx-preview'interface DocxOptions { bodyContainer?: HTMLElement | null styleContainer?: HTMLElement buffer: Blob docxOptions?: Partial<Record<string, string | boolean>>}exportconst renderDocx = (options: DocxOptions): Promise<void> | undefined => { if (typeofwindow !== '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) } }}
4.xlsx的预览方案
我们可以使用这个:
npm
地址:
www.npmjs.com/package/@vu…
[18]
支持
vue2
和
vue3
,也有
js
的版本
对于
xlsx
的预览方案,这个是找到最好用的了。
5.前端预览方案总结
我们对以上找到的优秀的解决方案,进行改进和总结,并封装成一个
web components
组件:
preview组件
[19]
为什么是
web components
组件?
因为它跟框架无关,可以在任何框架中使用,且使用起来跟原生的
div
标签一样方便。
并编写使用文档: preview组件文档 [20] , 文档支持交互体验。
源码公开,
MIT
协议。
目前
docx
,
pdf
,
xlsx
预览基本可以了,都是最好的方案。
pptx
预览效果不太好,因为需要自行解析。不过
源码完全公开
,需要的可以提
issue
,
pr
或者干脆自取或修改,源码地址:
github.com/chaxus/ran/…
[21]
3 服务端预览方案
1.openOffice
由于浏览器不能直接打开
docx
,
pptx
,
xlsx
等格式文件,但可以直接打开
pdf
和图片.因此,我们可以换一个思路,用服务端去转换下文件的格式,转换成浏览器能识别的格式,然后再让浏览器打开,这不就OK了吗,甚至不需要前端处理了。
我们可以借助
openOffice
的能力,先介绍一下
openOffice
:
Apache OpenOffice
是领先的开源办公软件套件,用于文字处理,电子表格,演示文稿,图形,数据库等。它有多种语言版本,适用于所有常用计算机。它以国际开放标准格式存储您的所有数据,还可以从其他常见的办公软件包中读取和写入文件。它可以出于任何目的完全免费下载和使用。
官网如下: www.openoffice.org/ [22]
需要先下载
opneOffice
,找到
bin
目录,进行设置
configuration.setOfficeHome("这里的路径一般为C:\\Program Files (x86)\\OpenOffice 4");
测试下转换的文件路径
publicstaticvoidmain(String[] args){ convertToPDF("/Users/Desktop/asdf.docx", "/Users/Desktop/adsf.pdf");}
完整如下:
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 classOfficeUtil{ privatestatic OfficeManager officeManager; privatestaticint port[] = {8100}; /** * start openOffice service. */publicstaticvoidstartService(){ DefaultOfficeManagerConfiguration configuration = new DefaultOfficeManagerConfiguration(); try { System.out.println("准备启动office转换服务...."); configuration.setOfficeHome("这里的路径一般为C:\\Program Files (x86)\\OpenOffice 4"); 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. */publicstaticvoidstopService(){ System.out.println("准备关闭office转换服务...."); if (officeManager != null) { officeManager.stop(); } System.out.println("office转换服务关闭成功!"); } publicstaticvoidconvertToPDF(String inputFile, String outputFile){ startService(); System.out.println("进行文档转换转换:" + inputFile + " --> " + outputFile); OfficeDocumentConverter converter = new OfficeDocumentConverter(officeManager); converter.convert(new File(inputFile), new File(outputFile)); stopService(); } publicstaticvoidmain(String[] args){ convertToPDF("/Users/koolearn/Desktop/asdf.docx", "/Users/koolearn/Desktop/adsf.pdf"); }}
2.kkFileView
github
地址:
github.com/kekingcn/kk…
[23]
支持的文件预览格式非常丰富
接下来是
从零到一
的启动步骤,按着步骤来,任何人都能搞定
安装
java
:
brew install java
安装
maven
,java
的包管理工具:
brew install mvn
检查是否安装成功
执行
java --version
和
mvn -v
。我这里遇到
mvn
找不到
java home
的报错。解决方式如下:
我用的是
zsh
,所以需要去
.zshrc
添加路径:
export JAVA_HOME=$(/usr/libexec/java_home)
添加完后,执行
source .zshrc
安装下
libreoffice
:
kkFileView
明确要求的额外依赖,否则无法启动
brew install libreoffice
mvn
安装依赖
进入项目,在根目录执行依赖安装,同时清理缓存,跳过单测(遇到了单测报错的问题)
mvn clean install -DskipTests
启动项目
找到主文件,主函数
mian
,点击
vscode
上面的
Run
即可执行,路径如下图
访问页面
启动完成后,点击终端输出的地址
最终结果
最终展示如下,可以添加链接进行预览,也可以选择本地文件进行预览
预览效果非常好
3.onlyOffice
官网地址: www.onlyoffice.com/zh [24]
github
地址:
github.com/ONLYOFFICE
[25]
开发者版本和社区版免费,企业版付费: www.onlyoffice.com/zh/docs-ent… [26]
预览的文件种类没有
kkFileView
多,但对
office
三件套有很好的支持,甚至支持多人编辑。
4 总结
外部服务,推荐微软的
view.officeapps.live.com/op/view.aspx
,但只建议预览一些互联网公开的文件,不建议使用在要求保密性和稳定性的文件。对保密性和稳定性有要求,且不差钱的,可以试试大厂服务,阿里云解决方案。
服务端技术比较给力的,使用服务端预览方案。目前最好最全的效果是服务端预览方案。
不想花钱,没有服务器的,使用前端预览方案,客户端渲染零成本。
5 参考文档:
在java中如何使用openOffice进行格式转换 [27]
MAC搭建OpenOffice完整教程-保姆级 [28]
纯js实现docx、xlsx、pdf文件预览库,使用超简单 [29]
前端实现word、excel、pdf、ppt、mp4、图片、文本等文件的预览 [30]
参考资料
[1]
answers.microsoft.com/en-us/msoff…:
https://answers.microsoft.com/en-us/msoffice/forum/all/what-is-the-status-of-viewofficeappslivecom/830fd75c-9b47-43f9-89c9-4303703fd7f6
help.aliyun.com/document_de…:
https://help.aliyun.com/document_detail/63273.html
view.xdocin.com/view-xdocin…:
https://view.xdocin.com/view-xdocin-com_6x5f4x.htm
www.officeweb365.com/:
https://www.officeweb365.com/
solution.wps.cn/:
https://solution.wps.cn/
github.com/g21589/PPTX…:
https://github.com/g21589/PPTX2HTML
officeopenxml:
http://officeopenxml.com/
officeopenxml-pptx:
http://officeopenxml.com/anatomyofOOXML-pptx.php
www.npmjs.com/package/jsz…:
https://www.npmjs.com/package/jszip
ranui:
https://github.com/chaxus/ran/tree/main/packages/ranui
preview组件:
https://chaxus.github.io/ran/src/ranui/preview/
www.npmjs.com/package/pdf…:
https://www.npmjs.com/package/pdfjs-dist
github.com/mozilla/pdf…:
https://github.com/mozilla/pdfjs-dist
github.com/mozilla/pdf…:
https://github.com/mozilla/pdf.js/blob/master/package.json
github.com/chaxus/ran/…:
https://github.com/chaxus/ran/tree/main/packages/ranui
chaxus.github.io/ran/src/ran…:
https://chaxus.github.io/ran/src/ranui/preview/
www.npmjs.com/package/doc…:
https://www.npmjs.com/package/docx-preview
www.npmjs.com/package/@vu…:
https://www.npmjs.com/package/@vue-office/excel
preview组件:
https://chaxus.github.io/ran/src/ranui/preview/
preview组件文档:
https://chaxus.github.io/ran/src/ranui/preview/
github.com/chaxus/ran/…:
https://github.com/chaxus/ran/tree/main/packages/ranui
www.openoffice.org/:
https://www.openoffice.org/
github.com/kekingcn/kk…:
https://github.com/kekingcn/kkFileView
www.onlyoffice.com/zh:
https://www.onlyoffice.com/zh
github.com/ONLYOFFICE:
https://github.com/ONLYOFFICE
www.onlyoffice.com/zh/docs-ent…:
https://www.onlyoffice.com/zh/docs-enterprise-prices.aspx
在java中如何使用openOffice进行格式转换:
https://blog.csdn.net/Li_Zhongxin/article/details/132105957
MAC搭建OpenOffice完整教程-保姆级:
https://blog.51cto.com/u_15899048/5902747
纯js实现docx、xlsx、pdf文件预览库,使用超简单:
https://juejin.cn/post/7251199685130059833
前端实现word、excel、pdf、ppt、mp4、图片、文本等文件的预览:
https://juejin.cn/post/7071598747519549454
欢迎有需要的同学试试,如果本文对您有帮助,也请帮忙点个 赞 + 在看 啦!❤️
你还有什么想要补充的吗?
最后,再次推荐下我们的AI星 球 :
为了跟上AI时代我干了一件事儿,我创建了一个知识星球社群:ChartGPT与副业。想带着大家一起探索 ChatGPT和新的AI时代 。
有很多小伙伴搞不定ChatGPT账号,于是我们决定,凡是这三天之内加入ChatPGT的小伙伴,我们直接送一个正常可用的永久ChatGPT独立账户。
不光是增长速度最快,我们的星球品质也绝对经得起考验,短短一个月时间,我们的课程团队发布了 8个专栏、18个副业项目 :
简单说下这个星球能给大家提供什么:
1、不断分享如何使用ChatGPT来完成各种任务,让你更高效地使用ChatGPT,以及副业思考、变现思路、创业案例、落地案例分享。
2、分享ChatGPT的使用方法、最新资讯、商业价值。
3、探讨未来关于ChatGPT的机遇,共同成长。
4、帮助大家解决ChatGPT遇到的问题。
5、 提供一整年的售后服务,一起搞副业
星球福利:
1、加入星球4天后,就送ChatGPT独立账号。
2、邀请你加入ChatGPT会员交流群。
3、赠送一份完整的ChatGPT手册和66个ChatGPT副业赚钱手册。
其它福利还在筹划中... 不过,我给你大家保证,加入星球后,收获的价值会远远大于今天加入的门票费用 !
本星球第一期原价 399 ,目前属于试运营,早鸟价 139 ,每超过50人涨价10元,星球马上要来一波大的涨价,如果你还在犹豫,可能最后就要以 更高价格加入了 。。
早就是优势。 建议大家尽早以便宜的价格加入!
欢迎有需要的同学试试,如果本文对您有帮助,也请帮忙点个 赞 + 在看 啦!❤️
在 还有更多优质项目系统学习资源,欢迎分享给其他同学吧!
PS:如果觉得我的分享不错,欢迎大家随手点赞、转发、在看。
最后给读者整理了一份BAT大厂面试真题,需要的可扫码加微信备注:「面试」获取。
版权申明:内容来源网络,版权归原创者所有。除非无法确认,我们都会标明作者及出处,如有侵权烦请告知,我们会立即删除并表示歉意。谢谢!
END
最近面试BAT,整理一份面试资料【Java面试BAT通关手册】,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。在这里,我为大家准备了一份2021年最新最全BAT等大厂Java面试经验总结。
别找了,想获取史上最全的Java大厂面试题学习资料
扫下方二维码回复「面试」就好了
历史好文:
扫码关注「后端架构师」,选择「星标」公众号
重磅干货,第一时间送达
嘿,你在看吗?