掃碼關註
「
後端架構師
」,選擇
「
星標
」
公眾號
重磅幹貨,第一時間送達!
責編:架構君 | 來源:然燃
連結: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大廠面試題學習資料
掃下方二維碼回復「面試」就好了
歷史好文:
掃碼關註「後端架構師」,選擇「星標」公眾號
重磅幹貨,第一時間送達
嘿,你在看嗎?