feat: 初始功能
This commit is contained in:
94
Services/Printing/RawPrintJobExecutor.cs
Normal file
94
Services/Printing/RawPrintJobExecutor.cs
Normal file
@@ -0,0 +1,94 @@
|
||||
using CloudPrint.Client.Helpers;
|
||||
using CloudPrint.Client.Models;
|
||||
using System.IO;
|
||||
|
||||
namespace CloudPrint.Client.Services.Printing;
|
||||
|
||||
public sealed class RawPrintJobExecutor : IPrintJobExecutor
|
||||
{
|
||||
public bool CanHandle(PrintJob job) => true;
|
||||
|
||||
public async Task ExecuteAsync(PrintJob job, IProgress<int>? progress, CancellationToken cancellationToken = default)
|
||||
{
|
||||
PrintFileGuards.EnsurePrintableFile(job);
|
||||
|
||||
if (!WindowsPrintApi.OpenPrinter(job.PrinterName, out var printerHandle, IntPtr.Zero))
|
||||
{
|
||||
throw new InvalidOperationException($"打开打印机失败:{job.PrinterName}");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var docInfo = new WindowsPrintApi.DocInfo
|
||||
{
|
||||
DocumentName = string.IsNullOrWhiteSpace(job.FileName) ? job.JobNo : job.FileName,
|
||||
DataType = "RAW"
|
||||
};
|
||||
|
||||
var windowsJobId = WindowsPrintApi.StartDocPrinter(printerHandle, 1, docInfo);
|
||||
if (windowsJobId == 0)
|
||||
{
|
||||
throw new InvalidOperationException("启动打印文档失败");
|
||||
}
|
||||
|
||||
job.WindowsJobId = windowsJobId;
|
||||
job.WindowsJobStatus = "已提交到 Windows 打印队列";
|
||||
|
||||
try
|
||||
{
|
||||
if (!WindowsPrintApi.StartPagePrinter(printerHandle))
|
||||
{
|
||||
throw new InvalidOperationException("启动打印页面失败");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await WriteFileToPrinterAsync(printerHandle, job.FilePath, progress, cancellationToken).ConfigureAwait(true);
|
||||
}
|
||||
finally
|
||||
{
|
||||
WindowsPrintApi.EndPagePrinter(printerHandle);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
WindowsPrintApi.EndDocPrinter(printerHandle);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
WindowsPrintApi.ClosePrinter(printerHandle);
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task WriteFileToPrinterAsync(IntPtr printerHandle, string filePath, IProgress<int>? progress, CancellationToken cancellationToken)
|
||||
{
|
||||
const int bufferSize = 64 * 1024;
|
||||
var buffer = new byte[bufferSize];
|
||||
var fileInfo = new FileInfo(filePath);
|
||||
long totalWritten = 0;
|
||||
|
||||
await using var stream = File.OpenRead(filePath);
|
||||
while (true)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
var read = await stream.ReadAsync(buffer.AsMemory(0, buffer.Length), cancellationToken).ConfigureAwait(true);
|
||||
if (read == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
var chunk = read == buffer.Length ? buffer : buffer[..read];
|
||||
if (!WindowsPrintApi.WritePrinter(printerHandle, chunk, read, out var written) || written != read)
|
||||
{
|
||||
throw new InvalidOperationException("写入打印机失败");
|
||||
}
|
||||
|
||||
totalWritten += written;
|
||||
var percent = fileInfo.Length == 0 ? 100 : (int)Math.Min(99, totalWritten * 100 / fileInfo.Length);
|
||||
progress?.Report(percent);
|
||||
}
|
||||
|
||||
progress?.Report(100);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user