开发中如果有这样的需求把 Image 图像转化为 PDF 文件你会怎么做呢?你可能会在网上狂找资料寻找解决方案,但是事实上网上这方面的资料非常少,有的作者没有给出一个完整的内容或者给出的内容不适合现在的需求、有错误误导读者,本次 Chat 集合了我四五年工作经验的体会,把这个技术分享给大家。

本场 Chat 你能学会的东西:

  1. iText 非常著名的转化为 PDF 第三方框架
  2. Android 存储路径选择
  3. Android 文件转化为 PDF
  4. Android 把文件放入文件夹中任意查看

前言

要把 Image 图像转化为 PDF 文件,一般都会涉及非常著名的第三方库 iText,它是著名的开放项目,是用于生成 PDF 文档的一个 Java 类库。通过 iText 不仅可以生成 PDF 或 rtf 等文档,甚至可以将 XML、HTML 文件转化为 PDF 格式。

接下我会依次介绍以下内容:

  1. iText 框架的使用;
  2. 使用 iText 生成 PDF 文件;
  3. Android 存储路径选择;
  4. Android 把文件放入文件夹中任意查看。

iText 框架的使用

iText 是一个软件开发者平台,用 Java 和 .NET 编写,允许您将 PDF 功能集成到您的应用程序,流程或产品中。其主要优势在于:

  • 为 Java 和 .NET 开发人员提供简单的 PDF 生成和操作;
  • 帮助您减少公司内的手动文档流程和纸张成本。

这里为大家提供下 iText 官网地址、官方开发文档网址、官方下载地址,供大家进一步了解它。

下面看下官方主页,如下图所示。

在这里对于英文不太好的读者简单的说一下官网的内容(英文好的可以略过)。

  • PRODUCTS:是对 iText 这个产品的介绍,里面包含有老版本的 iText 5 和最新的 iText 7 库,然后分别介绍 iText 5 和 iText 7 各个子模块的内容和效果展示。
  • RESOURCES:里面主要包含 iText 相关的书籍和 API 文档。
  • FOR DEVELOPERS:主要针对开发人员看的,包含各种例子教程和资源下载。

官方下载页面,如下图所示:

这里是对 iText 开源的库文件下载,一般库文件比较大,下载下来比较慢。在这里我介绍另外一种下载方法,大家可以访问这里,通过资源中心在里面搜索你想要的资源(jar包)下载。

官方开发文档页面,如下图所示:

虽然官方文档讲的比较清楚,但是你不通过爬过很多坑,看过密密麻麻的英文和过滤掉一大推对开发无用的文章,你很难很快完全掌握它的,而且官方的文档也是只言片语,集成到应用中还是要花费很多精力和时间,另外最新 iText7 接口是收费的,不可能把整个实现过程公布出来。

使用 iText 框架把 Image 生成 PDF 文件

要想把 Image 图像转化为 PDF 文件,需要先学习下面几个类的用法。

  • com.itextpdf.text.Document:这是 iText 库中最常用的类,它代表了一个 PDF 实例。如果你需要从零开始生成一个 PDF 文件,你需要使用这个 Document 类。首先创建(new)该实例,然后打开(open)它,并添加(add)内容,最后关闭(close)该实例,即可生成一个 PDF 文件。
  • com.itextpdf.text.Paragraph:表示一个缩进的文本段落,在段落中,你可以设置对齐方式,缩进,段落前后间隔等。
  • com.itextpdf.text.Chapter:表示 PDF 的一个章节,培训通过一个 Paragraph 类型的标题和整形章数创建。
  • com.itextpdf.text.Font:这个类包含了所有规范好的字体,包括字体、大小、样式和颜色,所有这些字体都被声明为静态常量。
  • com.itextpdf.text.List:表示一个列表;
  • cocom.itextpdf.text.List:表示一个列表;
  • com.itextpdf.text.Anchor:表示一个锚,类似于 HTML 页面的链接。
  • com.itextpdf.text.pdf.PdfWriter:当这个 PdfWriter 被添加到 PdfDocument 后,所有添加到 Document 的内容将会写入到与文件或网络关联的输出流中。
  • com.itextpdf.text.pdf.PdfReader:用于读取 PDF 文件;

通过这几个类中的方法,先生成一个 Document 对象,然后通过 PdfWriter.getInstance(document, new FileOutputStream(path)) 把 Document 对象写入路径中进去,生成一个空的 PDF 文件,接着 Document 对象把 Image 图像加入进来,最后关闭 Document 对象,Image 图像就加入到了空的 PDF 文件中了。

首先在 Eclipse 中验证代码的准确性。根据官方文档来写的,代码如下:

![enter image description here](http://images.gitbook.cn/b2a41840-1a29-11e8-8451-c901644501d9) /** * Example written by Bruno Lowagie in answer to the following question: * http://stackoverflow.com/questions/40336813/ */package sandbox.stamper;import com.itextpdf.text.DocumentException;import com.itextpdf.text.Image;import com.itextpdf.text.pdf.PdfContentByte;import com.itextpdf.text.pdf.PdfImage;import com.itextpdf.text.pdf.PdfIndirectObject;import com.itextpdf.text.pdf.PdfName;import com.itextpdf.text.pdf.PdfReader;import com.itextpdf.text.pdf.PdfStamper;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;/** * @author Bruno Lowagie (iText Software) */public class AddImageWithId {    public static final String SRC = "resources/pdfs/hello.pdf";    public static final String DEST = "results/stamper/hello_with_image_id.pdf";    public static final String IMG = "resources/images/bruno.jpg";    public static void main(String[] args) throws IOException, DocumentException {        File file = new File(DEST);        file.getParentFile().mkdirs();        new AddImageWithId().manipulatePdf(SRC, DEST);    }    public void manipulatePdf(String src, String dest) throws IOException, DocumentException {        PdfReader reader = new PdfReader(src);        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));        Image image = Image.getInstance(IMG);        PdfImage stream = new PdfImage(image, "", null);        stream.put(new PdfName("ITXT_SpecialId"), new PdfName("123456789"));        PdfIndirectObject ref = stamper.getWriter().addToBody(stream);        image.setDirectReference(ref.getIndirectReference());        image.setAbsolutePosition(36, 400);        PdfContentByte over = stamper.getOverContent(1);        over.addImage(image);        stamper.close();        reader.close();    }}

我把资源放在电脑桌面上了,如下代码:

public static final String SRC = "C:\\Users\\Administrator\\Desktop\\1.pdf";public static final String DEST = "C:\\Users\\Administrator\\Desktop\\2.pdf";public static final String IMG = "C:\\Users\\Administrator\\Desktop\\zq.jpg";

下面我们进行源码分析。

先 new 出一个 PdfReader 对象,然后通过输入文件路径 SRC 和输入路径 SEST,得到一个 PdfStamper 输出对象,stamper 对象会把 Image 图像加入进来,在加入图像之前会设置图像自己存放在 PDF 文件的位置,最后关闭 PdfReader 和 PdfStamper 对象。注意这里只需要:(1)PDF 文件和 zq.jpg 图像,否则会报错找不到资源;(2)PDF 文件程序会自动生成。

我们还可以用另外一种实现方式,这种方式跟上面的类似,不过加入了 PDF 文件格式排版方面的代码。

先贴代码,如下。

import com.itextpdf.text.Document;import com.itextpdf.text.DocumentException;import com.itextpdf.text.Image;import com.itextpdf.text.PageSize;import com.itextpdf.text.Paragraph;import com.itextpdf.text.pdf.PdfWriter;import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.util.ArrayList;/** * Created by steven on 2018/2/22. */public class PdfManager {    public static File     Pdf(ArrayList<String> imageUrllist, String mOutputPdfFileName) {        String TAG = "PdfManager";        Document doc = new Document(PageSize.A4, 20, 20, 20, 20);        try {            PdfWriter                    .getInstance(doc, new FileOutputStream(mOutputPdfFileName));            doc.open();            for (int i = 0; i < imageUrllist.size(); i++) {                doc.newPage();                doc.add(new Paragraph("简单使用iText"));                Image png1 = Image.getInstance(imageUrllist.get(i));                float heigth = png1.getHeight();                float width = png1.getWidth();                int percent = getPercent2(heigth, width);                png1.setAlignment(Image.MIDDLE);                png1.scalePercent(percent+3);// 表示是原来图像的比例;                doc.add(png1);            }            doc.close();        } catch (FileNotFoundException e) {            e.printStackTrace();        } catch (DocumentException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        }        File mOutputPdfFile = new File(mOutputPdfFileName);        if (!mOutputPdfFile.exists()) {            mOutputPdfFile.deleteOnExit();            return null;        }        return mOutputPdfFile;    }    /**     * 第一种解决方案 在不改变图片形状的同时,判断,如果h>w,则按h压缩,否则在w>h或w=h的情况下,按宽度压缩     *     * @param h     * @param w     * @return     */    public static int getPercent(float h, float w) {        int p = 0;        float p2 = 0.0f;        if (h > w) {            p2 = 297 / h * 100;        } else {            p2 = 210 / w * 100;        }        p = Math.round(p2);        return p;    }    /**     * 第二种解决方案,统一按照宽度压缩 这样来的效果是,所有图片的宽度是相等的,自我认为给客户的效果是最好的     *     * @param     */    public static int getPercent2(float h, float w) {        int p = 0;        float p2 = 0.0f;        p2 = 530 / w * 100;        p = Math.round(p2);        return p;    }}

在 main 中进行调用,代码如下:

public static void main(String[] args) {   // TODO Auto-generated method stub   ArrayList<String> imageUrllist = new ArrayList<String>();   imageUrllist.add("C:\\Users\\Administrator\\Desktop\\zq.jpg");   String pdfUrl = "C:\\Users\\Administrator\\Desktop\\zqzq.pdf";   File file = PdfManager.Pdf(imageUrllist, pdfUrl);   try {       file.createNewFile();   } catch (IOException e) {       // TODO Auto-generated catch block       e.printStackTrace();   }}

这种方式的思路是:首先创建(new)该实例,然后打开(open)它,并添加 Image,最后关闭(close)该实例.

Android 存储路径选择

首先科普下 Android 获取各个路径常用的方法。

(1)通过 Environment 获取。

  • Environment.getDataDirectory().getPath():获得根目录/data (内部存储路径)
  • Environment.getDownloadCacheDirectory().getPath():获得缓存目录/cache。
  • Environment.getExternalStorageDirectory().getPath():获得 SD 卡目录 /mnt/sdcard(获取的是手机外置 SD 卡的路径)。
  • Environment.getRootDirectory().getPath():获得系统目录/system。

(2)通过 Context 获取。

  • Context.getDatabasePath():返回通过 Context.openOrCreateDatabase 创建的数据库文件。
  • Context.getCacheDir().getPath():用于获取 App 的 cache 目录(/data/data/<application package>/cache 目录)。
  • Context.getExternalCacheDir().getPath():用于获取 App 在SD卡中的 cache 目录(/mnt/sdcard/Android/data/<application package>/cache)。
  • Context.getFilesDir().getPath():用于获取 App 的 files 目录(/data/data/<application package>/files)。
  • Context.getObbDir().getPath():用于获取 App SDK 中的 obb 目录(/mnt/sdcard/Android/obb/<application package>)。
  • Context.getPackageName():用于获取 App 的所在包目录。
  • Context.getPackageCodePath():来获得当前应用程序对应的 apk 文件的路径。

开发的时候需要把图像转换为 PDF 文件,一般会考虑放在外置或者内置 SD 卡上,如果没有外置 SD 卡或者 SD 卡不可用,那么可以用内置 SD 卡,获取外置 SD 卡路径的方法为:Context.getExternalCacheDir().getPath(),获取内置SD卡路径的方法为:Context.getCacheDir().getPath()。一般比较优秀的程序都会专门写一个方法来获取缓存地址,如下所示:

public File getPath(Context context, String fileName) {    String path;    if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())  || !Environment.isExternalStorageRemovable()) {        path=  Context.getExternalCacheDir().getPath();   } else {        path= Context.getCacheDir().getPath() ;  }   return new File(path + File.separator + fileName+".pdf");  }  

接下来生成一个 file 对象,代码如下:

File folder = getPath(context,"test")    if (!folder.exists()) {        boolean success = folder.mkdir();        if (!success) {           Toast.makeText(activity, "创建文件出现错误", Toast.LENGTH_SHORT).show();        }    }

下面是实现多个 Image 转化为 PDF,并加入到 test.pdf 文件中的代码:

      Document document = new Document(PageSize.A4, 38, 38, 50, 38);            Rectangle documentRect = document.getPageSize();            try {                PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(path));                document.open();                for (int i = 0; i < imagesUri.size(); i++) {                    Bitmap bmp = MediaStore.Images.Media.getBitmap(                            activity.getContentResolver(), Uri.fromFile(new File(imagesUri.get(i))));                    ByteArrayOutputStream stream = new ByteArrayOutputStream();                    bmp.compress(Bitmap.CompressFormat.PNG, 40, stream);                     String imageUrl = imagesUri.get(i);                     imageUrl  = imageUrl.replaceAll("~","_");                     image = Image.getInstance(imageUrl);                    if (bmp.getWidth() > documentRect.getWidth()                            || bmp.getHeight() > documentRect.getHeight()) {                        //bitmap is larger than page,so set bitmap's size similar to the whole page                        image.scaleAbsolute(documentRect.getWidth(), documentRect.getHeight());                    } else {                        //bitmap is smaller than page, so add bitmap simply.                        //[note: if you want to fill page by stretching image,                        // you may set size similar to page as above]                        image.scaleAbsolute(bmp.getWidth(), bmp.getHeight());                    }                    image.setAbsolutePosition(                            (documentRect.getWidth() - image.getScaledWidth()) / 2,                            (documentRect.getHeight() - image.getScaledHeight()) / 2);                    Log.v("Stage 7", "Image Alignments");                    image.setBorder(Image.BOX);                    image.setBorderWidth(15);                    document.add(image);                    document.newPage();                }            } catch (Exception e) {                e.printStackTrace();            }            document.close();            imagesUri.clear();

Android 把文件放入文件夹中任意查看

操作步骤主要有:

  1. 首先你得创建一个文件;
  2. 获得这个文件的路径,知道这个文件所在的文件夹;
  3. 打开文件夹,打开文件。

首先,创建一个文件上文也提到了,在这里再简单的写一遍,代码如下:

  String path,;  String filename ="test";     path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/PDFfiles/";            File folder = new File(path);            if (!folder.exists()) {                boolean success = folder.mkdir();                if (!success) {                    Toast.makeText(activity, "创建文件错误", Toast.LENGTH_SHORT).show();                    return null;                }            }            path = path + filename + ".pdf";

接下来,获取这个文件的路径,这个文件的路径就是上文的 path(文件名字是test.pdf)。

最后,找到文件夹,打开文件,直接贴代码,如下。

void openPdf() {    File file = new File(path);    Intent target = new Intent(Intent.ACTION_VIEW);    target.setDataAndType(Uri.fromFile(file), "application/pdf");    target.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);    Intent intent = Intent.createChooser(target,"Open File");    try {        startActivity(intent);    } catch (ActivityNotFoundException e) {        Toast.makeText(activity, R.string.toast_no_pdf_app, Toast.LENGTH_LONG).show();    }}

下面,我们解释一下代码的含义。

先生成一个 file 对象,path 是文件的完整路径(/storage/emulated/0/PDFfiles/test.pdf)。再 new 一个 Intent 对象,android.intent.action.VIEW 会根据用户的数据类型打开相应的 Activity,再把数据和类型放入,setDataAndType() 第一个方法是放入一个 Uri 对象,第二个参数是打开 PDF 文件类型默认的参数,setFlags 等下讲,Intent.createChooser(target,"Open File")是打开一个选择器,比如你手机装了福昕 PDF 和急速 PDF app,它会弹出一个选择框,让你选择用哪个阅读软件打开,createChooser()方法第一个参数传入 intent,也就是第三行代码生成的 Intent 对象,第二个参数传入一个字符串,它是选择框的标题,最后启动这个 intent:startActivity(intent)。

再来说下 target.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)。这行代码的意思是,如果设置 FLAG_ACTIVITY_NO_HISTORY 新的 Activity 将不再历史 stack 中保留。用户一离开它,这个 Activity 就关闭了。这也可以通过设置 noHistory 特性。这样用户打开 PDF 文件后,点击返回就回到了原来的 App 中了,target.setFlags()还有很多参数,现在贴出来大家一起学习下。

  • FLAG_ACTIVITY_BROUGHT_TO_FRONT

这个标志一般不是由程序代码设置的,如在 launchMode 中设置 singleTask 模式时系统帮你设定。

  • FLAG_ACTIVITY_CLEAR_TOP

如果设置,并且这个 Activity 已经在当前的 Task 中运行,因此,不再是重新启动一个这个 Activity 的实例,而是在这个 Activity 上方的所有 Activity 都将关闭,然后这个 Intent 会作为一个新的 Intent 投递到老的 Activity(现在位于顶端)中。例如,假设一个 Task 中包含这些 Activity:A、B、C、D。如果 D 调用了 startActivity(),并且包含一个指向 Activity B 的 Intent,那么,C 和 D 都将结束,然后 B 接收到这个 Intent,因此,目前 stack 的状况是:A、B。上例中正在运行的 Activity B 既可以在 onNewIntent() 中接收到这个新的 Intent,也可以把自己关闭然后重新启动来接收这个 Intent。如果它的启动模式声明为“multiple”(默认值),并且你没有在这个 Intent 中设置 FLAG_ACTIVITY_SINGLE_TOP 标志,那么它将关闭然后重新创建;对于其它的启动模式,或者在这个 Intent 中设置 FLAG_ACTIVITY_SINGLE_TOP 标志,都将把这个 Intent 投递到当前这个实例的 onNewIntent() 中。 这个启动模式还可以与 FLAG_ACTIVITY_NEW_TASK 结合起来使用:用于启动一个 Task 中的根 Activity,它会把那个 Task 中任何运行的实例带入前台,然后清除它直到根 Activity。这非常有用,例如,当从 Notification Manager 处启动一个 Activity。

  • FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET

如果设置,这将在 Task 的 Activity stack 中设置一个还原点。当 Task 恢复时,需要清理 Activity。也就是说,下一次 Task 带着 FLAG_ACTIVITY_RESET_TASK_IF_NEEDED 标记进入前台时(典型的操作是用户在主画面重启它),这个 Activity 和它之上的都将关闭,以至于用户不能再返回到它们,但是可以回到之前的 Activity。这在你的程序有分割点的时候很有用。例如,一个 E-mail 应用程序可能有一个操作是查看一个附件,需要启动图片浏览 Activity 来显示。这个 Activity 应该作为 E-mail 应用程序 Task 的一部分,因为这是用户在这个 Task 中触发的操作。然而,当用户离开这个 Task,然后从主画面选择 E-mail App,我们可能希望回到查看的会话中,但不是查看图片附件,因为这让人困惑。通过在启动图片浏览时设定这个标志,浏览及其它启动的 Activity 在下次用户返回到 mail 程序时都将全部清除。

  • FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

如果设置,新的 Activity 不会在最近启动的 Activity 的列表中保存。

  • FLAG_ACTIVITY_FORWARD_RESULT

如果设置,并且这个 Intent 用于从一个存在的 Activity 启动一个新的 Activity,那么,这个作为答复目标的 Activity 将会传到这个新的 Activity 中。这种方式下,新的 Activity 可以调用 setResult(int),并且这个结果值将发送给那个作为答复目标的 Activity。

  • FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY

这个标志一般不由应用程序代码设置,如果这个 Activity 是从历史记录里启动的(常按 HOME 键),那么系统会帮你设定。

  • FLAG_ACTIVITY_MULTIPLE_TASK

不要使用这个标志,除非你自己实现了应用程序启动器。与 FLAG_ACTIVITY_NEW_TASK 结合起来使用,可以禁用把已存的 Task 送入前台的行为。当设置时,新的 Task 总是会启动来处理 Intent,而不管是否已经有一个 Task 可以处理相同的事情。由于默认的系统不包含图形 Task 管理功能,因此,你不应该使用这个标志,除非你提供给用户一种方式可以返回到已经启动的 Task。如果 FLAG_ACTIVITY_NEW_TASK 标志没有设置,这个标志被忽略。

  • FLAG_ACTIVITY_NEW_TASK

如果设置,这个 Activity 会成为历史 stack 中一个新 Task 的开始。一个 Task(从启动它的 Activity 到下一个 Task 中的 Activity)定义了用户可以迁移的 Activity 原子组。Task 可以移动到前台和后台;在某个特定 Task 中的所有 Activity 总是保持相同的次序。这个标志一般用于呈现“启动”类型的行为:它们提供用户一系列可以单独完成的事情,与启动它们的 Activity 完全无关。使用这个标志,如果正在启动的 Activity 的 Task 已经在运行的话,那么,新的 Activity 将不会启动;代替的,当前 Task 会简单的移入前台。参考 FLAG_ACTIVITY_MULTIPLE_TASK 标志,可以禁用这一行为。这个标志不能用于调用方对已经启动的 Activity 请求结果。

  • FLAG_ACTIVITY_NO_ANIMATION

如果在 Intent 中设置,并传递给 Context.startActivity() 的话,这个标志将阻止系统进入下一个 Activity 时应用 Acitivity 迁移动画。这并不意味着动画将永不运行——如果另一个 Activity 在启动显示之前,没有指定这个标志,那么动画将被应用。这个标志可以很好的用于执行一连串的操作,而动画被看作是更高一级的事件的驱动。

  • FLAG_ACTIVITY_NO_HISTORY

如果设置,新的 Activity 将不再历史 stack 中保留。用户一离开它,这个 Activity 就关闭了。这也可以通过设置 noHistory 特性来实现。

  • FLAG_ACTIVITY_NO_USER_ACTION

如果设置,作为新启动的 Activity 进入前台时,这个标志将在 Activity 暂停之前阻止从最前方的 Activity 回调的 onUserLeaveHint()。典型的,一个 Activity 可以依赖这个回调,将用户的动作引起的 Activity 移出后台。这个回调在 Activity 的生命周期中标记一个合适的点,并关闭一些 Notification。如果一个 Activity 通过非用户驱动的事件,如来电或闹钟启动的,这个标志也应该传递给 Context.startActivity,保证暂停的 Activity 不认为用户已经知晓其 Notification。

  • FLAG_ACTIVITY_REORDER_TO_FRONT

如果在 Intent 中设置,并传递给 Context.startActivity(),这个标志将引发已经运行的 Activity 移动到历史 stack 的顶端。 例如,假设一个 Task 由四个 Activity 组成:A、B、C、D。如果 D 调用 startActivity() 来启动 Activity B,那么,B 会移动到历史 stack 的顶端,现在的次序变成 A、C、D、B。如果 FLAG_ACTIVITY_CLEAR_TOP 标志也设置的话,那么这个标志将被忽略。

  • FLAG_ACTIVITY_SINGLE_TOP

如果设置,当这个 Activity 位于历史 stack 的顶端运行时,不再启动一个新的。

好了,整个 Image 图像转化为 PDF 文件的知识点全部讲解完毕,希望大家通过这篇文章懂得了 Image 怎样转为 PDF 文件,并学以致用在开发中把功能更好更快的做出来,谢谢大家耐心的阅读。

本文的一个 Demo,可以到这里下载:下载地址.


本文首发于GitChat,未经授权不得转载,转载需与GitChat联系。

阅读全文: http://gitbook.cn/gitchat/activity/5a8f7431f2e5dc2ca621972f

您还可以下载 CSDN 旗下精品原创内容社区 GitChat App , GitChat 专享技术内容哦。

Image 图像转化为 PDF 文件相关推荐

  1. libreoffice将world、excel等文件转化为pdf文件

    我是用的linux系统,Centos: 第一步:需要下载libreoffice包,选择你直接想要的版本: 下载地址:https://zh-cn.libreoffice.org/download/lib ...

  2. 手机上将图片做成pdf_如何在Android上将多个图像合并为PDF文件

    手机上将图片做成pdf You've taken pictures of a paper document using your Android phone, and now you need to ...

  3. 怎样将ppt转化为pdf文件

    在职场工作当中ppt文件和pdf文件都是不可或缺的.Ppt文件通常用于工作会议.工作汇报等方面,而pdf文件则是用于文件的浏览查阅.文件的保存以及文件的打印.两种文件虽然是完全不同的形式,不同的作用, ...

  4. python win32转pdf 横版_解决pythoncom和win32com下docx文件转化为pdf文件过程中Word后台进程无法关闭的问题...

    1 目的 笔者在python3.6环境下,想把一个word文档转化为pdf文件.使用了以下的方式 from win32com import client import pythoncom doc2pd ...

  5. HTML转化为pdf文件并合并多个pdf文件

    HTML转化为pdf文件并合并多个pdf文件 转化的需要使用到  Wkhtmltopdf 这个工具. 下面代码的介绍; 首先我们要获取到web页面,然后把web页面转化为pdf文件,之后是合并pdf( ...

  6. 如何在VB.NET中把excel文件转化为PDF文件

    文章目录 一.如何在VB.NET中把excel文件转化为PDF文件 二.使用步骤 一.如何在VB.NET中把excel文件转化为PDF文件 基于之前获取打印机端口号的教程 二.使用步骤 代码如下(示例 ...

  7. 微信公众号文章转pdf下载,不难也不太容易,磕磕绊绊倒是不少如何用xpath保存网站源码;如何精简你的文章请求链接;如何将文章转化为pdf文件,不乱码,不报错

    目录 敲黑板 抓包分析 看碟下菜,确认分析思路 锁定有效数据包 分析响应信息和请求连接 黑板报 如何用xpath保存网站源码 如何精简你的文章请求链接 如何将文章转化为pdf文件,不乱码,不报错 总结 ...

  8. 使用PHP将Word文档转化为pdf文件(用户提交数据到Word模板并修改部分内容,再将Word转为PDF)

    需要实现的功能: 1.用户提交信息,例如:名称,年龄,电话等等 2.将这些信息填充到固定好的word模板中. 3.将生成的word转化为PDF. 4.使用的语言PHP 开始demo.docx文件中的内 ...

  9. java将HTML文件转化为pdf文件,如何使用Java将HTML网页转换为PDF文件

    我一直在互联网上搜索如何使用Java将HTML页面转换为PDF文件.我发现了很多指针,简而言之,它们不起作用或难以实现.我也下载了一个商业产品,pdf4ml;该API是我很乐意与之合作的,除了当我在维 ...

最新文章

  1. MySql的安装、配置(转)
  2. mysql索引查询 with_查找mysql中的低效索引
  3. 提高 webpack 构建 Vue 项目的速度
  4. c语言 read 文件字节没超过数组大小时会怎样_剑指信奥 | C 语言之信奥试题详解(四)...
  5. mysql语法_MySql实用技能,最常用的删除语法
  6. ISO9000和CMM
  7. 锐捷虚拟机做服务器,笨方法解决锐捷校园网环境下VMware虚拟机无法上网问题(Fedora试用上网成功)...
  8. 微信红包封面催生暴利灰产:有人月入三十万
  9. [免费配音软件]配音助手1.0 阿里云配音软件
  10. SRVCC B1,B2事件总结
  11. 050001 《拆掉思维里的墙》读后感——一些现象的解释
  12. maskrcnn-benchmark安装过程
  13. google colab使用入门
  14. 基于QT开发的开源局域网联机UNO卡牌游戏报告(附github仓库地址)
  15. 太空射击第14课: 玩家生命
  16. Matlab 基于遗传算法优化的VMD信号去噪算法 创新点:基于样本熵作为适应度函数
  17. pb11.5的使用体会
  18. Delphi 2007 代码补全、语句提示的快捷键是什么?
  19. 3Dmax与Maya哪个更实用
  20. 04 | 后台登录:基于账号密码的登录方式(上)

热门文章

  1. 微信公众号注册 步骤
  2. 使用sklearn训练模型出现【DataConversionWarning: A column-vector y was passed when a 1d array was expected】
  3. 5大原因告诉你,Python程序员为何如此难招!
  4. AD16快速上手指南(AD16为例)
  5. springboot 成员变量_SpringBoot就是这么简单
  6. Mapreduce统计
  7. Ubuntu和win10系统(N卡)
  8. LaTex特殊字符和符号
  9. java字面量和符号引用
  10. 一文带你深入浅出C语言数组