steven026 发表于 2023-10-9 11:13:58

[油猴脚本开发指南]实现静默打印、批量打印文件

# 背景
因为工作需要,经常会打印一些文件,比如pdf,但是量变引起质变,就算是简单的打印每次都要确认也会变得非常繁琐。
那么有没有简便的方法去打印文件呢?当然是有的,通常我们打印文件有两种途径。
(目前市面上打印机种类千奇百怪,但实际原理大同小异,建议阅读本文时注重原理,不要生搬硬套)
# 打印方法
## 调用打印机驱动程序打印
一般情况下程序的默认的打印均是通过OS系统自带的打印服务去打印机驱动程序实现打印。
前端浏览器一般只提供`window.print()`这一基础API,且只可打印当前页面,无法打印任意文件,仅少数格式文件支持在使用浏览器打开后单独打印(如pdf文件)
如果我们想要用油猴脚本去实现任意文件打印,可以参考
> [油猴脚本开发指南]前后端相结合实现静默下载
> https://bbs.tampermonkey.net.cn/thread-4944-1-1.html

将文件转发至后端服务器(如Node.js、Python等),然后让后端调用系统打印服务实现打印。
这种方法本文不再赘述,主要着重第二种方法。

## 调用打印机远程打印接口
(并非所有打印机都有远程打印功能,建议先参考打印机使用手册)
(且有些打印机远程打印只提供了exe程序,没有前端页面,这就需要通过额外工具进行抓包)
!(data/attachment/forum/202310/09/103238x2sbnjlscyiyqyj1.png)

本文以Fuji Xerox ApeosPort 4570为例,该型号打印机远程打印提供了一个本地网页UI。
通常情况下我们需要远程打印时可以在这个UI中上传文件,进行设定,再一次一次打印。
!(data/attachment/forum/202310/09/104825vgm0kdb0cby0hd5d.png)
!(data/attachment/forum/202310/09/104942wruf34x4sfdtx6xv.png)

我们可以打开控制台后先使用这个UI打印一次,然后观察控制台会发现刚才提交了一次请求,查看请求内容。
可以发现,我们通过ajax发送了一个POST请求到打印机远程接口,并将文件二进制内容以及打印设置存放在FormData中作为POST数据发送了出去。
并没有其他什么特殊内容,那么就非常简单了,我们直接将这个ajax请求转化为GMxhr请求,这就使得我们可以在油猴中实现任意打印这一需求。

### 参考代码(注重原理)
```js
const pdf = await new Promise((resolve) =>
    GM_xmlhttpRequest({
      // 从指定url下载文件
      // 文件格式需要是打印机支持打印的格式 否则需要提前转换
      // 如果是本地url,需要在浏览器插件设置中允许脚本管理器访问本地url
      url: 'file://D:/test.pdf',
      responseType: 'blob', // 以Blob形式接收文件 二进制方便直接转换为打印机接口需要的File
      onload: (xhr) => {
            console.log(xhr);
            resolve(xhr.response); // 二进制Blob
      },
    })
);

const file = new File(, 'a.pdf'); // 将Blob转为File

const config = {
    PrintMode: 'NORMAL',
    UserName: '',
    StartTime: '',
    EncryptKey: '',
    PrintQuantity: '1',
    PaperSize: 'UNKNOWN',
    PaperType: 'UNSPECIFIED',
    PaperInTray: 'AUTO',
    TwoSidedPrinting: 'ONESIDED',
    CollateMode: 'UNSPECIFIED',
    OutputDestination: '0_CENTER_UPPER',
    File: file, // 二进制pdf文件内容
};
const formData = new FormData();
Object.keys(config).forEach((key) => {
    formData.append(key, config); // 将设置及文件构造为FormData
});

GM_xmlhttpRequest({
    url: 'http://192.168.1.243/home/api/uploadfile-print?methodName=POST', // 打印机远程打印接口
    method: 'POST',
    data: formData, // FormData不要设置Content-Type,浏览器会读取boundary并自动设置,手动设置会覆盖自动设置,导致FormData无法被正常读取
    responseType: 'json',
    onload: (xhr) => {
      console.log(xhr);
      console.log(xhr.response);
    },
});
```
### 参考结果
!(data/attachment/forum/202310/09/110744vgqbxy2p31g2t00o.png)

***

至此已实现了静默打印,如需批量打印,只需将函数封装,循环调用即可,这里不在赘述,就当一个小小的课后作业,自己实现吧。

# 完结撒花~
工作效率又提升了呢~😘

王一之 发表于 2023-10-9 11:40:21

[油猴脚本开发指南]操作本地文件
https://bbs.tampermonkey.net.cn/thread-3079-1-1.html
(出处: 油猴中文网)

感觉可以结合这个来搞?

steven026 发表于 2023-10-9 11:45:58

王一之 发表于 2023-10-9 11:40
[油猴脚本开发指南]操作本地文件
https://bbs.tampermonkey.net.cn/thread-3079-1-1.html
(出处: 油猴中文 ...

之前试过一次这个API,感觉限制有点多,而且每次都要授权=-=
感觉这是前端安全性的极限了,再多就越权了,到时候全是恶意插件

王一之 发表于 2023-10-20 14:52:05

快警示一下,差点浪费400张纸

steven026 发表于 2023-10-20 14:59:13

王一之 发表于 2023-10-20 14:52
快警示一下,差点浪费400张纸

呜呜呜 破打印机不支持PNG直接打印
把的我PNG识别为文本了……

李恒道 发表于 2023-10-20 15:21:06

steven026 发表于 2023-10-20 14:59
呜呜呜 破打印机不支持PNG直接打印
把的我PNG识别为文本了……

会不会类型问题

steven026 发表于 2023-10-20 15:22:30

李恒道 发表于 2023-10-20 15:21
会不会类型问题

!(data/attachment/forum/202310/20/152204h4hjiinzezji3j84.png)
打印机问题,就是不支持PNG……一定要先转换一次
页: [1]
查看完整版本: [油猴脚本开发指南]实现静默打印、批量打印文件