ByteScope

PowerPoint 簡報(pptx)檔案格式

Office Open XML 格式的 Microsoft PowerPoint 簡報。

MIME 類型
application/vnd.openxmlformats-officedocument.presentationml.presentation
副檔名
.pptx
分類
文件

Magic number(檔案簽章)

0x00000000504B0304PK··'PK' — it is a ZIP

ZIP 內含 '[Content_Types].xml' 以及一個 'ppt/' 目錄。

關於 PowerPoint 簡報(pptx)格式

.pptx 是一個 Open Packaging Conventions 套件:一個 ZIP,裡面的元件描述投影片、版面配置與投影片母片,還有它們引用的媒體。ppt/presentation.xml 定義投影片順序,每個 ppt/slides/slideN.xml 放一張投影片的圖形與文字,圖片和影片則以一般檔案的形式躺在 ppt/media/ 底下。因為媒體是直接存進去而不是嵌在標記裡,一份簡報的體積幾乎全是圖片——所以想把簡報裡每張圖抓出來,最快的方式就是把 ZIP 解開。

檔頭結構,一個位元組一個位元組看

位移長度欄位意義
04Local file header signature50 4B 03 04——這個檔案就是 ZIP,在這個位移上,它和 Word 文件、活頁簿、電子書或一般壓縮檔完全分不出來。「它是簡報」這件事,全寄託在項目名稱上。
42Version needed to extract最低讀取端版本乘以 10,小端序。deflate 是 20。內嵌大型影片的簡報,是 OOXML 家族裡真的會撞到 4 GiB 上限、需要 45 走 ZIP64 的那一種。
62General purpose bit flag位元 3 把 CRC 與大小搬到資料後面的 data descriptor,位元 11 宣告名稱是 UTF-8。從桌面直接拖進來的媒體檔名常常不是 ASCII,所以簡報裡位元 11 被設起來的頻率比文件高。
82Compression methodXML 元件都是 8。ppt/media/ 底下的媒體則常常用方法 0 直接存,因為把已經壓過的 JPEG 或 MP4 再 deflate 一次只花時間、沒有收穫——所以大型簡報的 ZIP 裡多半是原封不動的位元組。
102Last modified timeMS-DOS 打包的時間,解析度兩秒、沒有時區。PowerPoint 會把這些正規化;真正有意義的製作日期在套件內的 docProps/core.xml。
122Last modified dateMS-DOS 打包的日期,年份從 1980 起算,所以更早的時間表達不出來,匯入的舊媒體會通通落在 1980-01-01。
144CRC-32只涵蓋這個元件未壓縮內容的檢查碼。簡報可能只有一張圖壞掉,每張投影片的 XML 卻都驗得過,所以壞掉的 .pptx 常常是文字完整、只有一張圖破掉。
184Compressed size這個元件儲存的位元組數。用方法 0 直接存的媒體項目,這個值會和未壓縮大小完全相同——在 hex dump 裡快速判斷哪些項目是原始媒體,靠的就是這點。
224Uncompressed size原始長度。把整個壓縮檔裡這兩個大小欄位對照著看,簡報的形狀就一目了然:少數幾個超好壓的 XML 元件,加上一長串壓不動的媒體。
262File name length[Content_Types].xml 依慣例被排在套件最前面時(每個 OOXML 寫入端都這麼排),這裡是 13 00,也就是 19 個位元組。這是檔案裡第一個帶資訊量的欄位。
282Extra field lengthPowerPoint 自己寫出來是 0。重新打包的工具會在這裡加上 Unix 權限與時間戳記的額外欄位,一張投影片都沒動,檔案的雜湊值卻變了。
3019First entry name[Content_Types].xml。它針對 /ppt/presentation.xml 的 Override 帶著一個結尾為 presentationml.presentation 的內容型別,那就是套件自己對「我是什麼」的宣告,比任何副檔名都權威。
variablevariableppt/presentation.xml讓這個套件成為簡報的元件。它不在固定位移——要透過中央目錄找到它。它按播放順序列出投影片 id,各自經由 ppt/_rels/presentation.xml.rels 解析到 ppt/slides/slideN.xml 元件,所以檔名裡的編號不必和實際順序一致。
-224End of central directory signature50 4B 05 06,在壓縮檔註解為空時位於倒數第 22 個位元組。讀取端是從這裡開始列舉投影片的,所以簡報打不打得開,取決於檔案尾巴有沒有活下來。
-64Offset of the central directory目錄的絕對位元組位置,前提同上。只要在檔案前面加東西就會壞掉,而 PowerPoint 的反應是回報簡報損毀,不會試著自己校正那段位移。

怎麼跟長得像的格式分開

容易搞混的怎麼分
Word 文件(docx)同一種套件格式、不同的內容物,整個本地檔案標頭一樣,位移 30 也一樣。決勝在中央目錄:ppt/presentation.xml 加一棵 ppt/ 樹,對上 word/document.xml 加一棵 word/ 樹。[Content_Types].xml 元件也會在它的 Override 內容型別裡明講自己是哪一種。
ppt前輩是 Compound File Binary 容器,開頭 D0 CF 11 E0 A1 B1 1A E1,裡面有一個名字就叫 'PowerPoint Document' 的串流。兩者都被叫做「PowerPoint 檔」、都用同一個程式打開,但內部沒有任何共通處——新格式是一包 XML 的 ZIP,舊格式是一個由二進位記錄組成的迷你檔案系統。
ZIP它就是 ZIP,所以問題是「哪一種 ZIP」。測試必須是正面的:套件根目錄有 [Content_Types].xml 加 _rels/.rels 就是 OOXML,再有一個 ppt/ 目錄就是簡報。一個剛好含有名為 ppt 的資料夾的普通壓縮檔不是簡報,因為那兩個必備元件它都沒有。
pptm啟用巨集的兄弟格式,在標頭層級能看到的地方全都逐位元組相同。差別是多一個 ppt/vbaProject.bin 元件,以及宣告的內容型別不同。把 .pptm 改名成 .pptx 在結構上什麼都沒變,所以只有把套件拆開才知道你手上的是哪一種。

常見的壞法

  • 壓縮檔尾巴掉了。投影片仍然完整地壓在檔案裡,PowerPoint 卻拒絕開啟,因為投影片列舉是從 end-of-central-directory 記錄開始的。往後掃 50 4B 03 04 重建目錄,通常每張投影片、每張圖都救得回來。
  • 50 4B 03 04 前面被塞了位元組。下載時先抓到一頁錯誤頁,整個套件就偏移了,中央目錄裡的絕對位移再也落不到真正的標頭上。每張投影片其實都在;把前面那段位元組拿掉就復原了。
  • 文字模式傳輸。換行轉換破壞了 deflate 資料流,但每個標頭欄位與項目名稱都還讀得懂,所以套件列得出來,然後在解壓縮某張投影片時 CRC 不符。用方法 0 存的媒體同樣會被默默弄壞,症狀是圖破掉而不是跳錯誤。
  • 單一媒體項目損壞。因為圖片和影片就是一般的 ZIP 項目,一張壞圖不影響任何投影片 XML 的驗證,只會在某一張投影片上顯示成「圖片遺失」的佔位。這是 .pptx 在真實世界最常見的失效,而且完全侷限在那一個項目。
  • 重新打包時結構弄錯了。手改投影片 XML 再重新壓縮,出錯的方式很多:把資料夾也加成目錄項目、改了名稱大小寫、在 XML 宣告前面加了 BOM,任何一項都會做出一個「每個 ZIP 工具都說健康、PowerPoint 說損毀」的套件。

這個格式現在還在用嗎

.pptx 套件是預設的簡報格式,而且沒有受到什麼實質威脅,因為簡報是少數沒有像樣替代標準的文件類型——Keynote 和 Google Slides 都是選擇匯入匯出它,而不是想取代它。當成容器來看它設計得不錯:開放的 ISO 標準、媒體以一般檔案儲存所以抽取很容易、元件是 XML 所以簡報壞掉大致救得回來。它實務上的問題全在體積與保真度。因為媒體是內嵌而非引用,一份放了十幾張原尺寸照片和一支影片的簡報動輒好幾百 MB,然後就這樣被寄來寄去;又因為算繪結果取決於字型、版面配置與繼承來的母片,簡報在缺字型的機器上打開會重排,每個文字方塊都跑掉。最後這個問題正是簡報定稿寄出前常常先轉成 PDF 的原因——編輯階段用可編輯格式,交付階段用固定版面格式。如果只是要從別人的簡報裡抽素材,直接把它當成它本來的樣子(一個 ZIP)處理,比一張張另存圖片更快,而且無損。

在這個站上打開 PowerPoint 簡報(pptx)檔

這些全部在你的瀏覽器裡跑,檔案不會離開你的電腦。

相關格式

容易和 PowerPoint 簡報(pptx)搞混的格式,可以比對它們的開頭位元組。

格式開頭位元組副檔名
Word 文件(docx)50 4B 03 04.docx
Excel 活頁簿(xlsx)50 4B 03 04.xlsx
ZIP50 4B 03 04.zip
OLE2 / CFBD0 CF 11 E0 A1 B1.doc

常見問題

檔案的 magic number 是什麼?

檔案開頭的前幾個位元組,不管檔名寫什麼,它標明的是真正的格式。PNG 一定以 89 50 4E 47 開頭,ZIP 則是 50 4B 03 04。作業系統、瀏覽器和 file 指令讀的都是這幾個位元組,而不是相信副檔名 — 這就是為什麼把檔案改名並不會改變它實際上是什麼。

我要怎麼自己檢查 magic number?

在 macOS 或 Linux 上,xxd -l 16 檔名 會印出前 16 個位元組;在 Windows 上,PowerShell 的 Format-Hex -Path 檔名 -Count 16。或者把檔案丟進本站的檔案類型辨識工具,它會在本機讀取位元組並告訴你是什麼格式,不會上傳任何東西。

為什麼兩種格式的 magic number 會一樣?

因為其中一種是建立在另一種之上。docx、xlsx、pptx、apk、jar 與 epub 骨子裡都是 ZIP 壓縮檔,所以全都以 ZIP 的簽章開頭;要分辨它們得看裡面的項目。Java class 檔和 macOS 的通用二進位檔都以 CA FE BA BE 開頭,靠緊接其後的欄位區分。

有完全沒有 magic number 的檔案嗎?

有。XML、HTML、JSON、SVG、CSV 這類以文字為基礎的格式沒有固定的位元組簽章,所以改用結構來辨識:開頭的 <?xml 宣告、<svg 元素,或是 { 後面接著帶引號的鍵。這種偵測是合理推測而非確定,因此本參考頁會把這些格式標示為結構偵測。

magic number 相符就代表檔案安全嗎?

不代表。它告訴你的是格式,不是內容是否無害 — 一個貨真價實的 PDF 或 docx 仍然可能夾帶惡意內容。辨識真實類型是有用的第一道檢查,尤其在副檔名和位元組不一致的時候,但它不是惡意軟體掃描。

手上有檔案可能是 PowerPoint 簡報(pptx)?用檔案類型辨識工具查出來 — 它在本機讀取 magic number,不上傳任何東西。或者瀏覽所有格式。