当前位置: 首页 > news >正文

Adobe PDF Reader实现旋转PDF功能

阅读目录

实现效果:
问题点:Adobe PDF Reader中并没有可以直接旋转的方法
解决办法:引入PdfiumViewer旋转PDF并保存替换当前的文件。
回到顶部
实现效果:
PDF旋转功能

回到顶部
问题点:Adobe PDF Reader中并没有可以直接旋转的方法
LoadFile 加载文件,文件URL地址
GotoFirstPage 到第一页
GotoLastPage 到最后一页
GotoPreviousPage 上一页
GotoNextPape 下一页
SetCurrentpage 到指定页
Setshowscrollbars 设置是否显示 Acrobat Reader的滚动条。带一个参数,该参数设为0时不显示滚动条,设为1时显示滚动条
SetshowToolbar 设置是否显示 Acrobat Reader的工具栏。带一个参数,该参数设为时不显示,设为1时显示。
Setview 设置显示效果。Fit:适应窗口大小; FitH:适合宽度
setZoom 设置文件的显示比例;默认是100
回到顶部
解决办法:引入PdfiumViewer旋转PDF并保存替换当前的文件。
///


/// 旋转保存PDF文件并释放文件锁定
///

///
///
///
///
public bool SafeSavePdfWithRelease(AxAcroPDFLib.AxAcroPDF axControl, string filePath, PdfRotation pdfRotation)
{
const int MAX_RETRY = 3;
const int RETRY_DELAY = 500;

    for (int attempt = 0; attempt < MAX_RETRY; attempt++){try{// 步骤1:创建临时副本string tempPath = Path.GetTempFileName().Replace(".tmp", ".pdf");File.Copy(filePath, tempPath, true);// 步骤2:使用内存流操作using (var ms = new MemoryStream(File.ReadAllBytes(tempPath)))using (var document = PdfiumViewer.PdfDocument.Load(ms)){for (int pageIndex = 0; pageIndex < document.PageCount; pageIndex++){document.RotatePage(pageIndex, pdfRotation);// 可选:验证旋转结果// var currentRotation = document.Pages[pageIndex].Rotation;// Debug.Assert(currentRotation == (int)rotation);}// 执行修改操作(示例:旋转第一页)//document.RotatePage(1, PdfRotation.Rotate90);// 步骤3:保存到临时文件byte[] pdfBytes;using (var outputStream = new MemoryStream()){document.Save(outputStream);pdfBytes = outputStream.ToArray();}// 步骤4:强制释放文件锁定ForceReleasePdfFile(axControl, filePath);// 步骤5:原子替换文件File.WriteAllBytes(tempPath, pdfBytes);// File.Replace(tempPath, filePath, null, true);// 1. 复制替换文件到目标路径File.Copy(tempPath, filePath, overwrite: true);// 2. 删除临时文件(可选)File.Delete(tempPath);// 步骤6:验证加载axControl.LoadFile(filePath);return true;}}catch (IOException ex) when (ex.HResult == -2147024864){if (attempt == MAX_RETRY - 1) throw;Thread.Sleep(RETRY_DELAY);}}return false;
}
public void ForceReleasePdfFile(AxAcroPDFLib.AxAcroPDF axControl, string filePath)
{// 步骤1:深度释放COM对象ReleaseComObject(axControl);// 步骤2:内核级文件解锁UnlockFileHandle(filePath);// 步骤3:延迟重载验证Thread.Sleep(200);axControl.LoadFile(filePath);
}private void ReleaseComObject(AxAcroPDFLib.AxAcroPDF axControl)
{try{// 显式释放ActiveX资源if (axControl.IsDisposed) return;// 反射调用内部释放方法var type = axControl.GetType();var method = type.GetMethod("ReleaseOCX", BindingFlags.Instance | BindingFlags.NonPublic);method?.Invoke(axControl, null);// 强制垃圾回收GC.Collect();GC.WaitForPendingFinalizers();}catch (Exception ex){}
}
// 修改后的P/Invoke声明
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern IntPtr CreateFile(string lpFileName,uint dwDesiredAccess,uint dwShareMode,IntPtr lpSecurityAttributes,FileMode dwCreationDisposition,  // 改用.NET枚举FileAttributes dwFlagsAndAttributes,  // 改用.NET枚举IntPtr hTemplateFile);// 修改后的UnlockFileHandle方法
private void UnlockFileHandle(string filePath)
{const uint FILE_SHARE_READ = 0x00000001;const uint FILE_SHARE_WRITE = 0x00000002;const uint GENERIC_READ = 0x80000000;IntPtr hFile = CreateFile(filePath,GENERIC_READ,FILE_SHARE_READ | FILE_SHARE_WRITE,IntPtr.Zero,FileMode.Open,  // 对应原生OPEN_EXISTINGFileAttributes.Normal,  // 对应原生FILE_ATTRIBUTE_NORMALIntPtr.Zero);if (hFile != IntPtr.Zero && hFile != new IntPtr(-1)){CloseHandle(hFile);}
}[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr hObject);`

调用代码:

	  /// <summary>/// 当前旋转角度/// </summary>public static int currentRotation = 0;/// <summary>/// 逆时针旋转/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void pictureEdit3_Click(object sender, EventArgs e){if (axAcroPDF1.Visible){currentRotation -= 90; PdfRotation pdfRotation = GetCounterClockwiseRotation(currentRotation);var path = axAcroPDF1.src;//调用旋转PDF保存方法SafeSavePdfWithRelease(axAcroPDF1, path,pdfRotation); axAcroPDF1.LoadFile(path);axAcroPDF1.setView("Fit"); //适应窗口大小}}/// <summary>/// 顺时针旋转/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void pictureEdit2_Click(object sender, EventArgs e){if (axAcroPDF1.Visible){currentRotation += 90; PdfRotation pdfRotation = GetCounterClockwiseRotation(currentRotation);var path = axAcroPDF1.src;//调用旋转PDF保存方法SafeSavePdfWithRelease(axAcroPDF1, path, pdfRotation);axAcroPDF1.LoadFile(path);axAcroPDF1.setView("Fit"); //适应窗口大小 }}/// <summary>/// 通过旋转度数计算旋转的角度/// </summary>/// <param name="counterClockwiseDegrees">当前旋转角度</param>public static PdfRotation GetCounterClockwiseRotation(int counterClockwiseDegrees){const int fullCircle = 360;int effectiveDegrees = counterClockwiseDegrees % fullCircle;if (effectiveDegrees < 0) effectiveDegrees += fullCircle; // 处理负角度if (currentRotation >= 360) {currentRotation = 0;}if (currentRotation <= -360) {currentRotation = 0;}switch (effectiveDegrees){case 90:return PdfRotation.Rotate90; case 180:return PdfRotation.Rotate180;case 270:return PdfRotation.Rotate270;case 0:default:return PdfRotation.Rotate0;}}/// <summary>
http://www.wxhsa.cn/company.asp?id=896

相关文章:

  • start.bat
  • 外泌体适配体筛选的 SELEX 技术:5 大核心方法拆解,精准捕捉 “细胞信使”
  • 知识点 AlexNet(2/8)
  • QtCreator问题输出框 MSVC编译出现中文乱码报错
  • Gitee DevOps本土化实践:为中国开发者打造全流程效能引擎
  • pip安装临时使用清华源
  • nginx 企业
  • java毕业设计-基于jspm网上书店管理系统(源码+LW+部署文档+全bao+远程调试+代码讲解等) - 详解
  • redis scan命令替换keys 命令
  • 聊一聊 .NET 某企业ECM内容管理系统 内存暴涨分析
  • SQL之字符串问题大坑
  • 可编辑区域
  • ES 跨订单的详情全局分页 解决
  • macbook pro2012怎么安装windows系统
  • docker-compose安装PostgreSQL和pgvector向量数据库
  • 【连续五届稳定检索、院士杰青云集】第六届先进材料与智能制造国际学术会议(ICAMIM 2025)
  • macbook airװwindowsϵͳ
  • 微信小程序语音转文字
  • 解决 windows远程桌面报错“CredSSP加密数据库修正”
  • 官网Chat对话 vs. API调用:本质区别与优化策略 - 浪矢
  • 【原创软件】第15期:免费好用的Excel合并软件,无需安装office也可以合并
  • 有关于简道云模式选择的思考
  • 详细介绍:80(HTTP默认端口)和8080端口(备用HTTP端口)区别
  • 一加9pro安卓14降级到安卓13记录
  • 【科普系列】隐藏在OSI模型里的“交通指挥员”——UDS会话层
  • openssl编程之sm2加解密代码示例
  • list对象转json_json转list对象集合
  • Gitee(码云)中国本土领先的代码托管与研发协作平台
  • H5游戏性能优化系列-----总纲
  • 阿里云边缘安全加速ESA保障服务安全