在 PHP 中管理簡報 BLOB 以有效使用記憶體
概述
Aspose.Slides 提供基於 BLOB 的大型二進位資料處理,能在簡報中處理大型影像、音訊、視訊與簡報檔案時減少記憶體消耗。
本篇說明如何使用 BLOB 處理程序將大型媒體加入簡報、從簡報匯出大型媒體,以及更有效率地載入大型簡報。也說明在處理過程中如何使用暫存檔案,以及如何變更儲存暫存檔案的資料夾。
關於 BLOB
BLOB (Binary Large Object) 通常是以二進位格式儲存的大型項目(照片、簡報、文件或媒體)。
Aspose.Slides for PHP via Java 讓您在涉及大型檔案時,以降低記憶體消耗的方式使用 BLOB。
Info
為了繞過與串流互動時的某些限制,Aspose.Slides 可能會複製串流的內容。透過串流載入大型簡報會導致簡報內容被複製,從而造成載入緩慢。因此,當您打算載入大型簡報時,我們強烈建議使用簡報檔案路徑而非串流。使用 BLOB 減少記憶體消耗
透過 BLOB 將大型檔案加入簡報
Aspose.Slides for Java 允許您透過 BLOB 程序將大型檔案(此處為大型影片檔)加入簡報,以降低記憶體消耗。
此 Java 範例說明如何透過 BLOB 程序將大型影片檔加入簡報:
$pathToVeryLargeVideo = "veryLargeVideo.avi";
# 建立一個新簡報,將影片加入其中
$pres = new Presentation();
try {
$fileStream = new Java("java.io.FileInputStream", $pathToVeryLargeVideo);
try {
# 讓我們將影片加入簡報 - 我們選擇 KeepLocked 行為,因為我們
# 不打算存取 "veryLargeVideo.avi" 檔案。
$video = $pres->getVideos()->addVideo($fileStream, LoadingStreamBehavior->KeepLocked);
$pres->getSlides()->get_Item(0)->getShapes()->addVideoFrame(0, 0, 480, 270, $video);
# 儲存簡報。當大型簡報輸出時,記憶體消耗
# 在整個 pres 物件的生命週期中保持低水平
$pres->save("presentationWithLargeVideo.pptx", SaveFormat::Pptx);
} finally {
if (!java_is_null($fileStream)) {
$fileStream->close();
}
}
} catch (JavaException $e) {
} finally {
if (!java_is_null($pres)) {
$pres->dispose();
}
}
透過 BLOB 從簡報匯出大型檔案
Aspose.Slides for PHP via Java 允許您透過 BLOB 程序從簡報匯出大型檔案(例如音訊或視訊檔)。舉例來說,您可能需要從簡報中擷取大型媒體檔案,但不想將檔案載入電腦記憶體。透過 BLOB 程序匯出檔案,可保持低記憶體消耗。
以下程式碼示範上述操作:
$hugePresentationWithAudiosAndVideosFile = "LargeVideoFileTest.pptx";
$loadOptions = new LoadOptions();
# 鎖定來源檔案且不將其載入記憶體
$loadOptions->getBlobManagementOptions()->setPresentationLockingBehavior(PresentationLockingBehavior->KeepLocked);
# 建立 Presentation 實例,鎖定 "hugePresentationWithAudiosAndVideos.pptx" 檔案。
$pres = new Presentation($hugePresentationWithAudiosAndVideosFile, $loadOptions);
try {
# 讓我們將每個影片儲存為檔案。為了避免大量記憶體使用,我們需要使用緩衝區
# 將簡報中影片串流的資料傳輸到新建立的影片檔案的串流。
$Array = new JavaClass("java.lang.reflect.Array");
$Byte = new JavaClass("java.lang.Byte");
$buffer = $Array->newInstance($Byte, 8 * 1024);
# 遍歷所有影片
for($index = 0; $index < java_values($pres->getVideos()->size()) ; $index++) {
$video = $pres->getVideos()->get_Item($index);
# 開啟簡報影片串流。請注意,我們特意避免存取屬性
# 如 video.BinaryData —— 因為此屬性會返回包含完整影片的位元組陣列,進而
# 導致位元組被載入記憶體。我們使用 video.GetStream,它會返回 Stream —— 且不會
# 要求我們將整個影片載入記憶體。
$presVideoStream = $video->getStream();
try {
$outputFileStream = new Java("java.io.FileOutputStream", "video" . $index . ".avi");
try {
$bytesRead;
while ($bytesRead = $presVideoStream->read($buffer, 0, java_values($Array->getLength($buffer))) > 0) {
$outputFileStream->write($buffer, 0, $bytesRead);
}
} finally {
$outputFileStream->close();
}
} finally {
$presVideoStream->close();
}
# 無論影片或簡報的大小,記憶體消耗都會保持低。
}
# 如有需要,您也可以對音訊檔案套用相同步驟。
} catch (JavaException $e) {
} finally {
$pres->dispose();
}
將影像以 BLOB 方式加入簡報
使用 ImageCollection 類別的方法,您可以將大型影像以串流方式加入,讓它被視為 BLOB。
此 PHP 程式碼說明如何透過 BLOB 程序加入大型影像:
$pathToLargeImage = "large_image.jpg";
# 建立一個新的簡報,將影像加入其中。
$pres = new Presentation();
try {
$fileStream = new Java("java.io.FileInputStream", $pathToLargeImage);
try {
# 讓我們將影像加入簡報 - 我們選擇 KeepLocked 行為,因為我們
# 並不打算存取 "largeImage.png" 檔案。
$img = $pres->getImages()->addImage($fileStream, LoadingStreamBehavior->KeepLocked);
$pres->getSlides()->get_Item(0)->getShapes()->addPictureFrame(ShapeType::Rectangle, 0, 0, 300, 200, $img);
# 儲存簡報。當大型簡報輸出時,記憶體消耗
# 在整個 pres 物件的生命週期中保持低水平
$pres->save("presentationWithLargeImage.pptx", SaveFormat::Pptx);
} finally {
if (!java_is_null($fileStream)) {
$fileStream->close();
}
}
} catch (JavaException $e) {
} finally {
if (!java_is_null($pres)) {
$pres->dispose();
}
}
記憶體與大型簡報
通常,載入大型簡報需要大量暫存記憶體。整個簡報的內容會被載入記憶體,而載入來源的檔案則不再使用。
以包含 1.5 GB 影片檔案的大型 PowerPoint 簡報 (large.pptx) 為例,以下 PHP 程式碼描述了標準載入方式:
$pres = new Presentation("large.pptx");
try {
$pres->save("large.pdf", SaveFormat::Pdf);
} finally {
if (!java_is_null($pres)) {
$pres->dispose();
}
}
但此方法會消耗約 1.6 GB 的暫存記憶體。
以 BLOB 載入大型簡報
透過 BLOB 程序,您可以在使用極少記憶體的情況下載入大型簡報。以下 PHP 程式碼說明了使用 BLOB 程序載入 large.pptx 的實作方式:
$loadOptions = new LoadOptions();
$loadOptions->getBlobManagementOptions()->setPresentationLockingBehavior(PresentationLockingBehavior->KeepLocked);
$loadOptions->getBlobManagementOptions()->setTemporaryFilesAllowed(true);
$pres = new Presentation("large.pptx", $loadOptions);
try {
$pres->save("large.pdf", SaveFormat::Pdf);
} finally {
if (!java_is_null($pres)) {
$pres->dispose();
}
}
變更暫存檔案的資料夾
使用 BLOB 程序時,電腦會在預設的暫存資料夾中建立暫存檔。如果您希望將暫存檔放置於其他資料夾,可透過 setTempFilesRootPath 變更儲存設定:
$loadOptions = new LoadOptions();
$loadOptions->getBlobManagementOptions()->setPresentationLockingBehavior(PresentationLockingBehavior->KeepLocked);
$loadOptions->getBlobManagementOptions()->setTemporaryFilesAllowed(true);
$loadOptions->getBlobManagementOptions()->setTempFilesRootPath("temp");
Info
使用setTempFilesRootPath 時,Aspose.Slides 不會自動建立儲存暫存檔的資料夾,您必須自行手動建立該資料夾。
釋放簡報物件以釋放記憶體
處理大型簡報時,請確保正確釋放 Presentation 實例,以釋放其佔用的記憶體。完成簡報使用後,呼叫 dispose() 以釋放非受管理資源。
$presentation = new Presentation("large.pptx");
# ...處理簡報...
$presentation->save("large.pdf", SaveFormat::Pdf);
# 明確釋放資源。
$presentation->dispose();
常見問題
什麼資料在 Aspose.Slides 簡報中會被視為 BLOB 並受 BLOB 選項控制?
大型二進位物件,如影像、音訊與視訊,都會被視為 BLOB。整個簡報檔案在載入或儲存時亦涉及 BLOB 處理。這些物件受 BLOB 原則管理,可讓您在需要時將記憶體使用量轉移至暫存檔。
在載入簡報時,我該在哪裡設定 BLOB 處理規則?
使用 LoadOptions 搭配 BlobManagementOptions。在此處您可設定 BLOB 的記憶體上限、是否允許暫存檔、暫存檔根目錄,以及來源鎖定行為。
BLOB 設定會影響效能嗎?該如何在速度與記憶體之間取得平衡?
會的。將 BLOB 完全保留在記憶體中可提升速度,但會增加 RAM 使用量;降低記憶體上限會將更多工作轉移至暫存檔,降低 RAM 消耗,但會產生額外 I/O。可使用 setMaxBlobsBytesInMemory 取得適合您的工作負載與環境的平衡。
在開啟極大簡報(如數 GB)時,BLOB 選項有幫助嗎?
有。BlobManagementOptions 專為此類情境設計:啟用暫存檔並使用來源鎖定可顯著降低峰值 RAM 使用量,讓處理極大簡報更加穩定。
我可以在從串流而非磁碟檔載入時使用 BLOB 原則嗎?
可以。相同的規則同樣適用於串流:簡報實例可以擁有並鎖定輸入串流(取決於選擇的鎖定模式),且在允許的情況下會使用暫存檔,以在處理期間保持可預測的記憶體使用量。