混合方向PDF每页打印为横向
IronPrint 2026.1.5 在打印既有纵向也有横向页面的PDF时,不会保留每页的方向。 每一页不论原始方向如何,最终都会以横向打印。
这影响2026.1.5 在Windows 10和Windows Server 2022上的.NET 8版本。此版本没有修正的构建。
引擎会对整个文档应用单一方向,而不是读取每页的尺寸。 将文件分割为相同方向页面的运行,单独打印每个运行可以恢复正确的输出。
解决方案
推荐: 将PDF以方向一致的批次进行打印,而不是作为单个任务。
1. 检测每页的方向
打开PDF,比较每一页的宽度和高度。 比高度宽的页面是横向; 其他的是纵向。
2. 分组连续相同方向的页面
按顺序遍历页面,每当方向翻转时开始一个新的批次。 每个批次最后都会形成一个相同方向的连续页面范围。
3. 将每个批次作为独立任务进行打印
分别发送每个范围,允许打印机应用该范围的方向,而不是将整个文档强制为横向。
4. 手动处理多个副本
因为文档现在分布在多个任务中,需对每个副本循环一次,并每次打印完整的批次序列。这使每个副本内的页面顺序保持完整。
完整实施:
using IronPrint;
using IronPdf;
await PrintDocumentByOrientationBatchesAsync(
documentPath: documentPath,
printerName: printerName,
numberOfCopies: effectiveCopies);
async Task PrintDocumentByOrientationBatchesAsync(
string documentPath,
string printerName,
int numberOfCopies)
{
var tempFolder = Path.Combine(
Path.GetTempPath(),
"ironprint-orientation-workaround",
Guid.NewGuid().ToString("N"));
Directory.CreateDirectory(tempFolder);
try
{
using var pdf = PdfDocument.FromFile(documentPath);
var batches = GetConsecutiveOrientationBatches(pdf);
// Since the document is printed in multiple jobs, copies are handled manually
// to preserve the full document order per copy.
for (var copy = 1; copy <= numberOfCopies; copy++)
{
foreach (var batch in batches)
{
var batchPath = Path.Combine(
tempFolder,
$"copy_{copy}_pages_{batch.StartPageNumber}_{batch.EndPageNumber}_{batch.Orientation}.pdf");
using var batchPdf = pdf.CopyPages(batch.StartIndex, batch.EndIndex);
batchPdf.SaveAs(batchPath);
var printSettings = new PrintSettings
{
PrinterName = printerName,
NumberOfCopies = 1,
PaperOrientation = batch.Orientation == DetectedPageOrientation.Landscape
? PaperOrientation.Landscape
: PaperOrientation.Portrait,
PaperSize = PaperSize.PrinterDefault
};
await Printer.PrintAsync(batchPath, printSettings);
// Optional delay to help ensure print jobs are queued in order.
await Task.Delay(500);
}
}
}
finally
{
try
{
Directory.Delete(tempFolder, recursive: true);
}
catch
{
// Ignore cleanup errors in case the print spooler is still accessing the files.
}
}
}
List<PageOrientationBatch> GetConsecutiveOrientationBatches(PdfDocument pdf)
{
var batches = new List<PageOrientationBatch>();
if (pdf.PageCount == 0)
{
return batches;
}
var currentOrientation = GetPageOrientation(pdf.Pages[0].Width, pdf.Pages[0].Height);
var batchStartIndex = 0;
for (var pageIndex = 1; pageIndex < pdf.PageCount; pageIndex++)
{
var page = pdf.Pages[pageIndex];
var pageOrientation = GetPageOrientation(page.Width, page.Height);
if (pageOrientation != currentOrientation)
{
batches.Add(new PageOrientationBatch(
StartIndex: batchStartIndex,
EndIndex: pageIndex - 1,
Orientation: currentOrientation));
batchStartIndex = pageIndex;
currentOrientation = pageOrientation;
}
}
batches.Add(new PageOrientationBatch(
StartIndex: batchStartIndex,
EndIndex: pdf.PageCount - 1,
Orientation: currentOrientation));
return batches;
}
DetectedPageOrientation GetPageOrientation(double width, double height)
{
return width > height
? DetectedPageOrientation.Landscape
: DetectedPageOrientation.Portrait;
}
record PageOrientationBatch(
int StartIndex,
int EndIndex,
DetectedPageOrientation Orientation)
{
public int StartPageNumber => StartIndex + 1;
public int EndPageNumber => EndIndex + 1;
}
enum DetectedPageOrientation
{
Portrait,
Landscape
}
using IronPrint;
using IronPdf;
await PrintDocumentByOrientationBatchesAsync(
documentPath: documentPath,
printerName: printerName,
numberOfCopies: effectiveCopies);
async Task PrintDocumentByOrientationBatchesAsync(
string documentPath,
string printerName,
int numberOfCopies)
{
var tempFolder = Path.Combine(
Path.GetTempPath(),
"ironprint-orientation-workaround",
Guid.NewGuid().ToString("N"));
Directory.CreateDirectory(tempFolder);
try
{
using var pdf = PdfDocument.FromFile(documentPath);
var batches = GetConsecutiveOrientationBatches(pdf);
// Since the document is printed in multiple jobs, copies are handled manually
// to preserve the full document order per copy.
for (var copy = 1; copy <= numberOfCopies; copy++)
{
foreach (var batch in batches)
{
var batchPath = Path.Combine(
tempFolder,
$"copy_{copy}_pages_{batch.StartPageNumber}_{batch.EndPageNumber}_{batch.Orientation}.pdf");
using var batchPdf = pdf.CopyPages(batch.StartIndex, batch.EndIndex);
batchPdf.SaveAs(batchPath);
var printSettings = new PrintSettings
{
PrinterName = printerName,
NumberOfCopies = 1,
PaperOrientation = batch.Orientation == DetectedPageOrientation.Landscape
? PaperOrientation.Landscape
: PaperOrientation.Portrait,
PaperSize = PaperSize.PrinterDefault
};
await Printer.PrintAsync(batchPath, printSettings);
// Optional delay to help ensure print jobs are queued in order.
await Task.Delay(500);
}
}
}
finally
{
try
{
Directory.Delete(tempFolder, recursive: true);
}
catch
{
// Ignore cleanup errors in case the print spooler is still accessing the files.
}
}
}
List<PageOrientationBatch> GetConsecutiveOrientationBatches(PdfDocument pdf)
{
var batches = new List<PageOrientationBatch>();
if (pdf.PageCount == 0)
{
return batches;
}
var currentOrientation = GetPageOrientation(pdf.Pages[0].Width, pdf.Pages[0].Height);
var batchStartIndex = 0;
for (var pageIndex = 1; pageIndex < pdf.PageCount; pageIndex++)
{
var page = pdf.Pages[pageIndex];
var pageOrientation = GetPageOrientation(page.Width, page.Height);
if (pageOrientation != currentOrientation)
{
batches.Add(new PageOrientationBatch(
StartIndex: batchStartIndex,
EndIndex: pageIndex - 1,
Orientation: currentOrientation));
batchStartIndex = pageIndex;
currentOrientation = pageOrientation;
}
}
batches.Add(new PageOrientationBatch(
StartIndex: batchStartIndex,
EndIndex: pdf.PageCount - 1,
Orientation: currentOrientation));
return batches;
}
DetectedPageOrientation GetPageOrientation(double width, double height)
{
return width > height
? DetectedPageOrientation.Landscape
: DetectedPageOrientation.Portrait;
}
record PageOrientationBatch(
int StartIndex,
int EndIndex,
DetectedPageOrientation Orientation)
{
public int StartPageNumber => StartIndex + 1;
public int EndPageNumber => EndIndex + 1;
}
enum DetectedPageOrientation
{
Portrait,
Landscape
}
Imports IronPrint
Imports IronPdf
Imports System.IO
Await PrintDocumentByOrientationBatchesAsync(documentPath:=documentPath, printerName:=printerName, numberOfCopies:=effectiveCopies)
Private Async Function PrintDocumentByOrientationBatchesAsync(documentPath As String, printerName As String, numberOfCopies As Integer) As Task
Dim tempFolder = Path.Combine(Path.GetTempPath(), "ironprint-orientation-workaround", Guid.NewGuid().ToString("N"))
Directory.CreateDirectory(tempFolder)
Try
Using pdf = PdfDocument.FromFile(documentPath)
Dim batches = GetConsecutiveOrientationBatches(pdf)
' Since the document is printed in multiple jobs, copies are handled manually
' to preserve the full document order per copy.
For copy = 1 To numberOfCopies
For Each batch In batches
Dim batchPath = Path.Combine(tempFolder, $"copy_{copy}_pages_{batch.StartPageNumber}_{batch.EndPageNumber}_{batch.Orientation}.pdf")
Using batchPdf = pdf.CopyPages(batch.StartIndex, batch.EndIndex)
batchPdf.SaveAs(batchPath)
Dim printSettings = New PrintSettings With {
.PrinterName = printerName,
.NumberOfCopies = 1,
.PaperOrientation = If(batch.Orientation = DetectedPageOrientation.Landscape, PaperOrientation.Landscape, PaperOrientation.Portrait),
.PaperSize = PaperSize.PrinterDefault
}
Await Printer.PrintAsync(batchPath, printSettings)
' Optional delay to help ensure print jobs are queued in order.
Await Task.Delay(500)
End Using
Next
Next
End Using
Finally
Try
Directory.Delete(tempFolder, recursive:=True)
Catch
' Ignore cleanup errors in case the print spooler is still accessing the files.
End Try
End Try
End Function
Private Function GetConsecutiveOrientationBatches(pdf As PdfDocument) As List(Of PageOrientationBatch)
Dim batches = New List(Of PageOrientationBatch)()
If pdf.PageCount = 0 Then
Return batches
End If
Dim currentOrientation = GetPageOrientation(pdf.Pages(0).Width, pdf.Pages(0).Height)
Dim batchStartIndex = 0
For pageIndex = 1 To pdf.PageCount - 1
Dim page = pdf.Pages(pageIndex)
Dim pageOrientation = GetPageOrientation(page.Width, page.Height)
If pageOrientation <> currentOrientation Then
batches.Add(New PageOrientationBatch(StartIndex:=batchStartIndex, EndIndex:=pageIndex - 1, Orientation:=currentOrientation))
batchStartIndex = pageIndex
currentOrientation = pageOrientation
End If
Next
batches.Add(New PageOrientationBatch(StartIndex:=batchStartIndex, EndIndex:=pdf.PageCount - 1, Orientation:=currentOrientation))
Return batches
End Function
Private Function GetPageOrientation(width As Double, height As Double) As DetectedPageOrientation
Return If(width > height, DetectedPageOrientation.Landscape, DetectedPageOrientation.Portrait)
End Function
Private NotInheritable Class PageOrientationBatch
Public Property StartIndex As Integer
Public Property EndIndex As Integer
Public Property Orientation As DetectedPageOrientation
Public Sub New(StartIndex As Integer, EndIndex As Integer, Orientation As DetectedPageOrientation)
Me.StartIndex = StartIndex
Me.EndIndex = EndIndex
Me.Orientation = Orientation
End Sub
Public ReadOnly Property StartPageNumber As Integer
Get
Return StartIndex + 1
End Get
End Property
Public ReadOnly Property EndPageNumber As Integer
Get
Return EndIndex + 1
End Get
End Property
End Class
Private Enum DetectedPageOrientation
Portrait
Landscape
End Enum
GetConsecutiveOrientationBatches 针对每个连续运行产生一个 PageOrientationBatch,并且 Printer.PrintAsync 用自己的 PaperOrientation 运行每个范围。 任务之间的 Task.Delay(500) 帮助调度程序按顺序排队。

