# 如何将不同尺寸的图片添加到PDF里

#### 问题现象

如何将不同尺寸的图片添加到PDF里？创建PDF文件时，createDocument(width: number, height: number)如果宽高定的过小会导致尺寸大一点的图片显示不全。

#### 效果预览

#### 背景知识

*   fs.listFileSync：默认以同步方式列出当前目录下所有文件名和目录名。支持过滤。
*   getImageInfoSync：以同步方法获取图像像素信息。
*   createDocument：创建空白文档。
*   insertBlankPage：在指定位置插入PDF页。
*   addImageObject：在PDF文档的页面中添加图片。
*   saveDocument：保存文档。

#### 解决方案

以将context.filesDir目录下图片添加到PDF为例。

1.  引入相关kit。
    
    ```
    import { common } from '@kit.AbilityKit';
    import { fileIo as fs, ListFileOptions } from '@kit.CoreFileKit';
    import { pdfService, PdfView, pdfViewManager } from '@kit.PDFKit';
    import { image } from '@kit.ImageKit';
    import { ArrayList } from '@kit.ArkTS';
    import { systemDateTime } from '@kit.BasicServicesKit';
    ```
    
2.  声明全局变量。
    
    ```
    private controller: pdfViewManager.PdfController = new pdfViewManager.PdfController();
    private context = this.getUIContext().getHostContext() as common.UIAbilityContext;
    ```
    
3.  使用PdfView组件展示PDF文件。
    
    ```
    PdfView({
      controller: this.controller,
      pageFit: pdfService.PageFit.FIT_PAGE,
      showScroll: false
    })
      .height('90%')
      .width('90%')
      .id('pdfview_app_view')
      .borderWidth(0)
      .layoutWeight(1);
    ```
    
4.  构造ImgInfo类。
    
    ```
    export class ImgInfo {
      path: string = '';
      width: number = 0;
      height: number = 0;
    }
    ```
    
5.  创建PDF文件。
    
    *   以所有图片中的最大宽高创建PDF文件。
        
        ```
        Button('根据所有图片中的最大宽高值创建PDF文件').onClick(async () => {
          // 获取目录下所有图片中的最大宽高值，并记录每张图片的路径、宽高（保证该沙箱目录下有对应格式图片）
          let dir: string = this.context.filesDir;
          let listFileOption: ListFileOptions = {
            recursion: false,
            listNum: 0,
            filter: {
              suffix: ['.png', '.jpg', '.jpeg']
            }
          };
          let imgInfoList: ArrayList = new ArrayList();
          let maxImgWidthNum: number = 0;
          let maxImgHeightNum: number = 0;
          let filenames = fs.listFileSync(dir, listFileOption);
          if (filenames.length <= 0) {
            console.info('no file be found');
            return;
          }
          // 遍历出目录下的图片文件
          for (let i = 0; i < filenames.length; i++) {
            console.info('filename: %s', filenames[i]);
            let imageSource = image.createImageSource(dir + '/' + filenames[i]);
            let imageInfo = imageSource.getImageInfoSync(0);
            // 记录图片路径、宽高信息
            let img = new ImgInfo();
            img.path = dir + '/' + filenames[i];
            img.width = imageInfo.size.width;
            img.height = imageInfo.size.height;
            imgInfoList.add(img);
            // 更新宽高最大值
            if (imageInfo.size.height > maxImgHeightNum) {
              maxImgHeightNum = imageInfo.size.height;
            }
            if (imageInfo.size.width > maxImgWidthNum) {
              maxImgWidthNum = imageInfo.size.width;
            }
          }
        
          // 创建PDF文件时以获取到的图片最大宽高值作为PDF文件的宽高，根据记录下来的图片信息调用addImageObject将图片添加到PDF中，并保存PDF文件
          let pdfDocument = new pdfService.PdfDocument();
          // 创建PDF文件，宽高为获取到的图片最大宽高值
          pdfDocument.createDocument(maxImgWidthNum, maxImgHeightNum);
          for (let index = 0; index < imgInfoList.length; index++) {
            let pdfPage: pdfService.PdfPage | undefined;
            if (index > 0) {
              // 插入空白页
              pdfDocument.insertBlankPage(index, maxImgWidthNum, maxImgHeightNum);
            }
            pdfPage = pdfDocument.getPage(index);
            // 将图片添加到PDF中
            pdfPage.addImageObject(imgInfoList[index].path, 0, 0, imgInfoList[index].width,
              imgInfoList[index].height);
          }
          let pdfFileName = systemDateTime.getTime().toString();
          let pdfFilePath = this.context.tempDir + `/${pdfFileName}.pdf`;
          // 保存PDF文件
          pdfDocument.saveDocument(pdfFilePath);
          this.controller.releaseDocument();
          // 将PDF文件加载到PdfView组件中
          let loadResult: pdfService.ParseResult = await this.controller.loadDocument(pdfFilePath, '');
          if (pdfService.ParseResult.PARSE_SUCCESS === loadResult) {
            this.controller.setPageZoom(1.5);
          }
        });
        ```
        
    *   创建PDF文件每页PDF的宽高跟随图片宽高。
        
        ```
        Button('创建PDF文件每页PDF的宽高跟随图片宽高').onClick(async () => {
          // 记录每张图片的路径、宽高（保证该沙箱目录下有对应格式图片）
          let dir: string = this.context.filesDir;
          let listFileOption: ListFileOptions = {
            recursion: false,
            listNum: 0,
            filter: {
              suffix: ['.png', '.jpg', '.jpeg']
            }
          };
          let imgInfoList: ArrayList = new ArrayList();
          let filenames = fs.listFileSync(dir, listFileOption);
          if (filenames.length <= 0) {
            console.info('no file be found');
            return;
          }
          // 遍历出目录下的图片文件
          for (let i = 0; i < filenames.length; i++) {
            console.info('filename: %s', filenames[i]);
            let imageSource = image.createImageSource(dir + '/' + filenames[i]);
            let imageInfo = imageSource.getImageInfoSync(0);
            // 记录图片路径、宽高信息
            let img = new ImgInfo();
            img.path = dir + '/' + filenames[i];
            img.width = imageInfo.size.width;
            img.height = imageInfo.size.height;
            imgInfoList.add(img);
          }
        
          // 创建PDF文件时每一页宽高跟随添加到该页的图片的宽高，根据记录下来的图片信息调用addImageObject将图片添加到PDF中，并保存PDF文件
          let pdfDocument = new pdfService.PdfDocument();
          // 创建PDF文件，第一页宽高跟随第一张图片宽高。
          pdfDocument.createDocument(imgInfoList[0].width, imgInfoList[0].height);
          for (let index = 0; index < imgInfoList.length; index++) {
            let pdfPage: pdfService.PdfPage | undefined;
            if (index > 0) {
              // 插入空白页，每一页宽高跟随图片宽高。
              pdfDocument.insertBlankPage(index, imgInfoList[index].width, imgInfoList[index].height);
            }
            pdfPage = pdfDocument.getPage(index);
            // 将图片添加到pdf中
            pdfPage.addImageObject(imgInfoList[index].path, 0, 0, imgInfoList[index].width,
              imgInfoList[index].height);
          }
          let pdfFileName = systemDateTime.getTime().toString();
          let pdfFilePath = this.context.tempDir + `/${pdfFileName}.pdf`;
          // 保存pdf文件
          pdfDocument.saveDocument(pdfFilePath);
          this.controller.releaseDocument();
          // 将PDF文件加载到PdfView组件中
          let loadResult: pdfService.ParseResult = await this.controller.loadDocument(pdfFilePath, '');
          if (pdfService.ParseResult.PARSE_SUCCESS === loadResult) {
            this.controller.setPageZoom(1.5);
          }
        });
        ```
        
    
    完整示例参考如下：
    
    ```
    import { common } from '@kit.AbilityKit';
    import { fileIo as fs, ListFileOptions } from '@kit.CoreFileKit';
    import { pdfService, PdfView, pdfViewManager } from '@kit.PDFKit';
    import { image } from '@kit.ImageKit';
    import { ArrayList } from '@kit.ArkTS';
    import { systemDateTime } from '@kit.BasicServicesKit';
    @Entry
    @Component
    struct PdfPreview {
      private controller: pdfViewManager.PdfController = new pdfViewManager.PdfController();
      private context = this.getUIContext().getHostContext() as common.UIAbilityContext;
    
      build() {
        Column({ space: 5 }) {
          PdfView({
            controller: this.controller,
            pageFit: pdfService.PageFit.FIT_PAGE,
            showScroll: false
          })
            .height('90%')
            .width('90%')
            .id('pdfview_app_view')
            .borderWidth(0)
            .layoutWeight(1);
    
          Button('根据所有图片中的最大宽高值创建PDF文件').onClick(async () => {
            // 获取目录下所有图片中的最大宽高值，并记录每张图片的路径、宽高（保证该沙箱目录下有对应格式图片）
            let dir: string = this.context.filesDir;
            let listFileOption: ListFileOptions = {
              recursion: false,
              listNum: 0,
              filter: {
                suffix: ['.png', '.jpg', '.jpeg']
              }
            };
            let imgInfoList: ArrayList = new ArrayList();
            let maxImgWidthNum: number = 0;
            let maxImgHeightNum: number = 0;
            let filenames = fs.listFileSync(dir, listFileOption);
            if (filenames.length <= 0) {
              console.info('no file be found');
              return;
            }
            // 遍历出目录下的图片文件
            for (let i = 0; i < filenames.length; i++) {
              console.info('filename: %s', filenames[i]);
              let imageSource = image.createImageSource(dir + '/' + filenames[i]);
              let imageInfo = imageSource.getImageInfoSync(0);
              // 记录图片路径、宽高信息
              let img = new ImgInfo();
              img.path = dir + '/' + filenames[i];
              img.width = imageInfo.size.width;
              img.height = imageInfo.size.height;
              imgInfoList.add(img);
              // 更新宽高最大值
              if (imageInfo.size.height > maxImgHeightNum) {
                maxImgHeightNum = imageInfo.size.height;
              }
              if (imageInfo.size.width > maxImgWidthNum) {
                maxImgWidthNum = imageInfo.size.width;
              }
            }
    
            // 创建PDF文件时以获取到的图片最大宽高值作为PDF文件的宽高，根据记录下来的图片信息调用addImageObject将图片添加到PDF中，并保存PDF文件
            let pdfDocument = new pdfService.PdfDocument();
            // 创建PDF文件，宽高为获取到的图片最大宽高值
            pdfDocument.createDocument(maxImgWidthNum, maxImgHeightNum);
            for (let index = 0; index < imgInfoList.length; index++) {
              let pdfPage: pdfService.PdfPage | undefined;
              if (index > 0) {
                // 插入空白页
                pdfDocument.insertBlankPage(index, maxImgWidthNum, maxImgHeightNum);
              }
              pdfPage = pdfDocument.getPage(index);
              // 将图片添加到PDF中
              pdfPage.addImageObject(imgInfoList[index].path, 0, 0, imgInfoList[index].width,
                imgInfoList[index].height);
            }
            let pdfFileName = systemDateTime.getTime().toString();
            let pdfFilePath = this.context.tempDir + `/${pdfFileName}.pdf`;
            // 保存PDF文件
            pdfDocument.saveDocument(pdfFilePath);
            this.controller.releaseDocument();
            // 将PDF文件加载到PdfView组件中
            let loadResult: pdfService.ParseResult = await this.controller.loadDocument(pdfFilePath, '');
            if (pdfService.ParseResult.PARSE_SUCCESS === loadResult) {
              this.controller.setPageZoom(1.5);
            }
          });
    
          Button('创建PDF文件每页PDF的宽高跟随图片宽高').onClick(async () => {
            // 记录每张图片的路径、宽高（保证该沙箱目录下有对应格式图片）
            let dir: string = this.context.filesDir;
            let listFileOption: ListFileOptions = {
              recursion: false,
              listNum: 0,
              filter: {
                suffix: ['.png', '.jpg', '.jpeg']
              }
            };
            let imgInfoList: ArrayList = new ArrayList();
            let filenames = fs.listFileSync(dir, listFileOption);
            if (filenames.length <= 0) {
              console.info('no file be found');
              return;
            }
            // 遍历出目录下的图片文件
            for (let i = 0; i < filenames.length; i++) {
              console.info('filename: %s', filenames[i]);
              let imageSource = image.createImageSource(dir + '/' + filenames[i]);
              let imageInfo = imageSource.getImageInfoSync(0);
              // 记录图片路径、宽高信息
              let img = new ImgInfo();
              img.path = dir + '/' + filenames[i];
              img.width = imageInfo.size.width;
              img.height = imageInfo.size.height;
              imgInfoList.add(img);
            }
    
            // 创建PDF文件时每一页宽高跟随添加到该页的图片的宽高，根据记录下来的图片信息调用addImageObject将图片添加到PDF中，并保存PDF文件
            let pdfDocument = new pdfService.PdfDocument();
            // 创建PDF文件，第一页宽高跟随第一张图片宽高。
            pdfDocument.createDocument(imgInfoList[0].width, imgInfoList[0].height);
            for (let index = 0; index < imgInfoList.length; index++) {
              let pdfPage: pdfService.PdfPage | undefined;
              if (index > 0) {
                // 插入空白页，每一页宽高跟随图片宽高。
                pdfDocument.insertBlankPage(index, imgInfoList[index].width, imgInfoList[index].height);
              }
              pdfPage = pdfDocument.getPage(index);
              // 将图片添加到pdf中
              pdfPage.addImageObject(imgInfoList[index].path, 0, 0, imgInfoList[index].width,
                imgInfoList[index].height);
            }
            let pdfFileName = systemDateTime.getTime().toString();
            let pdfFilePath = this.context.tempDir + `/${pdfFileName}.pdf`;
            // 保存pdf文件
            pdfDocument.saveDocument(pdfFilePath);
            this.controller.releaseDocument();
            // 将PDF文件加载到PdfView组件中
            let loadResult: pdfService.ParseResult = await this.controller.loadDocument(pdfFilePath, '');
            if (pdfService.ParseResult.PARSE_SUCCESS === loadResult) {
              this.controller.setPageZoom(1.5);
            }
          });
        }
        .width('100%')
        .height('100%');
      }
    }
    
    export class ImgInfo {
      path: string = '';
      width: number = 0;
      height: number = 0;
    }
    ```
    

#### 常见FAQ

Q：如何将自定义组件转为PDF文档？

A：使用组件截图将自定义组件截图为图片，然后可以将图片添加到PDF文档中。