常见问题
从指定的 PDF 文件路径打开一个 PDF 文档
如何从指定的 PDF 文件路径打开一个 PDF 文档?
在构造 PDFDoc 时,只能使用绝对路径。由于 HarmonyOS Next 的沙盒机制,您无法访问应用外文件的真实路径。因此,您需要先将文件拷贝到应用内部,然后再打开。请参考如下的代码:
js
@Entry
@Component
struct Index {
@State isShowDoc: boolean = false;
@State pdfViewModel: PDFViewCtrlModel = new PDFViewCtrlModel(getContext());
private appFilesDir = getContext().filesDir;
build() {
Column() {
if (!this.isShowDoc) {
Button('Open Doc')
.onClick(async ()=>{
const filePath = await this.selectFile();
if(filePath != null) {
this.isShowDoc = true;
this.pdfViewModel.openDoc(filePath);
}
})
} else {
PDFViewCtrl({ model: this.pdfViewModel })
}
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
async selectFile(): Promise<string | null> {
try {
let documentSelectOptions = new picker.DocumentSelectOptions();
// documentSelectOptions.fileSuffixFilters = suffix;
documentSelectOptions.maxSelectNumber = 10;
if (canIUse('SystemCapability.FileManagement.UserFileService.FolderSelection')) {
documentSelectOptions.selectMode = picker.DocumentSelectMode.FILE;
}
const documentViewPicker = new picker.DocumentViewPicker(getContext());
const documentSelectResult: Array<string> = await documentViewPicker.select(documentSelectOptions);
if (documentSelectResult.length === 0) {
return null;
}
const importFiles: Array<string> = new Array();
for (let i = 0; i < documentSelectResult.length; i++) {
let uri = documentSelectResult[i];
let src_file = fs.openSync(uri, fs.OpenMode.READ_ONLY);
src_file.path
const dest_filepath = this.appFilesDir + '/' + src_file.name;
fs.copyFileSync(src_file.fd, dest_filepath);
fs.closeSync(src_file.fd);
importFiles.push(dest_filepath);
}
return importFiles[0];
} catch (error) {
console.error(error);
}
return null;
}
}
打开 PDF 文档时显示指定的页面
如何在打开 PDF 文档时,显示指定的页面?
为了在打开 PDF 文档时显示指定的页面,您需要使用接口 pdfViewModel.gotoPage
。Foxit PDF SDK 鸿蒙版使用多线程来提高渲染速度,因此您需要确保在使用 pdfViewModel.gotoPage
接口之前,文档已经被成功加载。
请在 IDocEventListener 中实现回调接口,然后在 onDocOpened 事件中调用 gotoPage 接口。以下是示例代码:
js
import { FoxitRDKNative, IDocEventListener, PDFViewCtrl, PDFViewCtrlModel } from 'foxit_rdk';
import picker from '@ohos.file.picker';
import fs, { Filter, Options } from '@ohos.file.fs';
@Entry
@Component
struct Index {
@State isShowDoc: boolean = false;
@State pdfViewModel: PDFViewCtrlModel = new PDFViewCtrlModel(getContext());
private appFilesDir = getContext().filesDir;
build() {
Column() {
if (!this.isShowDoc) {
Button('Open Doc')
.onClick(async () => {
const filePath = await this.selectFile();
if (filePath != null) {
this.isShowDoc = true;
this.pdfViewModel.openDoc(filePath);
}
})
} else {
RelativeContainer() {
PDFViewCtrl({ model: this.pdfViewModel })
.id('pdfview')
.alignRules({
top: { anchor: "__container__", align: VerticalAlign.Top },
left: { anchor: "__container__", align: HorizontalAlign.Start }
})
Column() {
Button('Goto Last Page')
.onClick(() => {
const pageCount = this.pdfViewModel.getPageCount();
this.pdfViewModel.gotoPage(pageCount -1);
})
}
.width('100%')
.margin({ top: 100 })
.id('ToolAction')
}
.width('100%')
.height('100%')
}
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
aboutToAppear(): void {
this.pdfViewModel.registerDocEventListener(this.docEventListener);
}
aboutToDisappear(): void {
this.pdfViewModel.unregisterDocEventListener(this.docEventListener);
}
async selectFile(): Promise<string | null> {
try {
let documentSelectOptions = new picker.DocumentSelectOptions();
// documentSelectOptions.fileSuffixFilters = suffix;
documentSelectOptions.maxSelectNumber = 10;
if (canIUse('SystemCapability.FileManagement.UserFileService.FolderSelection')) {
documentSelectOptions.selectMode = picker.DocumentSelectMode.FILE;
}
const documentViewPicker = new picker.DocumentViewPicker(getContext());
// await select complete
const documentSelectResult: Array<string> = await documentViewPicker.select(documentSelectOptions);
if (documentSelectResult.length === 0) {
return null;
}
const importFiles: Array<string> = new Array();
for (let i = 0; i < documentSelectResult.length; i++) {
let uri = documentSelectResult[i];
let src_file = fs.openSync(uri, fs.OpenMode.READ_ONLY);
src_file.path
const dest_filepath = this.appFilesDir + '/' + src_file.name;
fs.copyFileSync(src_file.fd, dest_filepath);
fs.closeSync(src_file.fd);
importFiles.push(dest_filepath);
}
return importFiles[0];
} catch (error) {
console.error(error);
}
return null;
}
private docEventListener: IDocEventListener = {
onDocOpened: (document: FoxitRDKNative.pdf.PDFDoc, errCode: number): void => {
if (errCode == FoxitRDKNative.common.ErrorCode.e_ErrSuccess) {
const pageCount = this.pdfViewModel.getPageCount();
this.pdfViewModel.gotoPage(pageCount - 2);
}
}
}
}
License key 和序列号无法正常工作
从网站下载的 SDK 包,未进行任何更改,为什么 license key 和序列号无法正常工作?
通常,上传到网站的包,里面的 license key 和序列号是可以正常工作的。在上传到网站之前是经过测试的。因此,如果您发现 license key 和序列号无法使用,则可能是由设备的日期引起的。如果您设备的时间在下载包 "libs" 文件夹下 hosnsdk_key.txt 文件中的 StartDate 之前,则 "librdk.so" 库将无法解锁。请检查您设备的日期。
在 PDF 文档中添加 link 注释
如何在 PDF 文档中添加 link 注释?
为了将 link 注释添加到 PDF 文档,首先需要调用 PDFPage.AddAnnot
将一个 link 注释添加到指定页面,然后调用 Action.Create
创建一个 action,并将该 action 设置给刚添加的 link 注释。以下是在 PDF 首页添加一个 URI link 注释的示例代码:
js
import { FoxitRDKNative } from 'foxit_rdk';
class LinkUnit {
private addLinkAnnot() {
try {
const path = 'xxx/Sample.pdf'
// 初始化一个 PDFDoc 对象
const document = new FoxitRDKNative.pdf.PDFDoc(path);
// 加载未加密的文档内容
document.Load();
// 获取 PDF文件的第一页
const page = document.GetPage(0);
// 在第一页添加一个 link annotation
const linkAnnot = new FoxitRDKNative.pdf.annots.Link(page.AddAnnot(FoxitRDKNative.pdf.annots.Annot.e_Link,
new FoxitRDKNative.common.fxcrt.RectF(250, 650, 400, 750)));
// 创建一个 URI action 并设置 URI
const uriAction =
new FoxitRDKNative.pdf.actions.URIAction(FoxitRDKNative.pdf.actions.Action.Create(document,
FoxitRDKNative.pdf.actions.Action.e_TypeURI));
uriAction.SetURI("www.foxitsoftware.com");
// 将 action 设置给 link annotation
linkAnnot.SetAction(uriAction);
linkAnnot.ResetAppearanceStream();
// 保存已添加 link annotation 的文档
document.SaveAs("xxx/sample_link.pdf", FoxitRDKNative.pdf.PDFDoc.e_SaveFlagNormal);
} catch (e) {
console.error(e);
}
}
}
向 PDF 文档中插入图片
如何向 PDF 文档中插入图片?
有两种方法可以帮助您将图片插入到 PDF 文档中。第一钟是调用 PDFPage.AddImageFromFilePath
接口。您可以参考如下示例代码,该代码将图片插入到 PDF 文档的首页:
备注:在调用 PDFPage.AddImageFromFilePath
接口之前,您需要获取并解析将要添加图片的页面。
js
import { FoxitRDKNative } from 'foxit_rdk';
class ImageUnit {
//1
private addImage(): void {
try {
const path = "xxx/Sample.pdf";
// 初始化一个 PDFDoc 对象
const document = new FoxitRDKNative.pdf.PDFDoc(path);
// 加载未加密的文档内容
document.Load();
// 获取PDF文件的第一页
const page = document.GetPage(0);
// 解析页面
if (!page.IsParsed()) {
const parse = page.StartParse(FoxitRDKNative.pdf.PDFPage.e_ParsePageNormal, null, false);
let state = FoxitRDKNative.common.Progressive.e_ToBeContinued;
while (state == FoxitRDKNative.common.Progressive.e_ToBeContinued) {
state = parse.Continue();
}
}
// 在第一页添加一张图片
page.AddImageFromFilePath("XXX/2.png", new FoxitRDKNative.common.fxcrt.PointF(20, 30), 60, 50, true)
// 保存已添加图片的文档
document.SaveAs("XXX/sample_image.pdf", FoxitRDKNative.pdf.PDFDoc.e_SaveFlagNormal);
} catch (e) {
console.error(e);
}
}
}
第二种是使用 PDFPage.AddAnnot
接口在指定的页面添加一个 screen 注释,然后将图片设置给刚添加的 screen 注释。您可以参考以下的示例代码,该代码将图片作为 screen 注释插入到 PDF 文件的首页:
js
import { FoxitRDKNative } from 'foxit_rdk';
class ImageUnit {
private addScreenAnnot(): void {
try {
const path = "xxx/Sample.pdf";
// 初始化一个 PDFDoc 对象
const document = new FoxitRDKNative.pdf.PDFDoc(path);
// 加载未加密的文档内容
document.Load();
// 获取 PDF 文件的第一页
const page = document.GetPage(0);
// 在第一页添加一个 screen annotation
const screen = new FoxitRDKNative.pdf.annots.Screen(page.AddAnnot(FoxitRDKNative.pdf.annots.Annot.e_Screen,
new FoxitRDKNative.common.fxcrt.RectF(100, 350, 250, 150)));
// 加载一个本地图片
const image = new FoxitRDKNative.common.Image('xxx/test.png');
screen.SetImage(image, 0, 0);
screen.ResetAppearanceStream();
// 保存已添加 screen annotation 的文档
document.SaveAs("XXX/sample_image.pdf", FoxitRDKNative.pdf.PDFDoc.e_SaveFlagNormal);
} catch (e) {
console.error(e);
}
}
}
高亮 PDF 文档中的表单域和设置高亮颜色
如何设置是否高亮 PDF 文档中的表单域? 以及如何设置高亮的颜色?
默认情况下,高亮 PDF 文档中的表单域功能是启用的。如果您想要禁用它或者设置高亮颜色,可以通过JSON 文件或调用 API 进行设置。
备注:如果您需要设置高亮的颜色,请确保表单域高亮的功能是启用的。
通过 JSON 文件
设置 "highlightForm": false,
在 PDF 文档中禁用表单域高亮功能。 设置 "highlightFormColor": "#2000ffcc",
设置高亮颜色 (输入您需要的颜色值)。
通过调用 API
UIExtensionsManager.enableFormHighlight
接口用来设置是否在 PDF 文档中启用表单域高亮的功能。如果您不需要启用该功能,请将其参数设置为 "false",如下所示:
js
// 假设已经初始化一个UIExtensionsManager对象: uiextensionsManager
this.uiextensionsManager.enableFormHighlight (false);
UIExtensionsManager.setFormHighlightColor
接口用来设置高亮的颜色。以下是调用此 API 的示例代码:
js
// 假设已经初始化一个UIExtensionsManager对象: uiextensionsManager
this.uiextensionsManager.setFormHighlightColor(0x4b0000ff);
支持全文索引搜索
Foxit PDF SDK 鸿蒙版是否支持全文索引搜索?如果支持,如何搜索在我的移动设备上离线存储的 PDF 文件?
是的。Foxit PDF SDK 鸿蒙版支持全文索引搜索。
要使用此功能,请按照如下的步骤:
a) 根据目录来创建一个文档来源,该目录为文档的搜索目录。
js
DocumentsSource#constructor(directory: string);
b) 创建一个全文文本搜索对象,以及设置用于存储索引数据的数据库路径。
js
FullTextSearch#constructor();
FullTextSearch#SetDataBasePath(path_of_data_base: string): void;
c) 开始索引文档来源中的 PDF 文档。
js
FullTextSearch#StartUpdateIndex(source: DocumentsSource, pause: PauseCallback, reupdate: boolean): Progressive;
备注:您可以索引指定的PDF文件。例如,如果某个PDF文档的内容发生了更改,您可以使用以下的API对其重新进行索引:
js
FullTextSearch#UpdateIndexWithFilePath(file_path: string): boolean
d) 从索引数据源中搜索指定的内容。搜索的结果将通过指定的回调函数来返回给外部,每找到一个匹配结果,则调用一次回调函数。
js
FullTextSearch#SearchOf(match_string: string, rank_mode: number, callback: SearchCallback): boolean
如下是使用全文索引搜索的示例代码:
js
import { FoxitRDKNative } from 'foxit_rdk';
import { systemDateTime } from '@kit.BasicServicesKit';
class DocumentsSourceUnit {
private testSearch(): void {
try {
const directory = "A search directory...";
const search = new FoxitRDKNative.fts.FullTextSearch();
const dbPath = "The path of data base to store the indexed data...";
search.SetDataBasePath(dbPath);
// 获取文档源信息
const source = new FoxitRDKNative.fts.DocumentsSource(directory);
// 创建一个由用户实现的暂停回调对象,以暂停更新过程
const pauseCallback = new PauseCallbackImpl(30);
// 开始索引文档来源中的PDF文档
const progressive = search.StartUpdateIndex(source, pauseCallback, false);
let state = FoxitRDKNative.common.Progressive.e_ToBeContinued;
while (state == FoxitRDKNative.common.Progressive.e_ToBeContinued) {
state = progressive.Continue();
}
// 创建一个回调对象,当找到匹配项时将被调用
const searchCallback = new MySearchCallback();
// 从索引的数据源中搜索指定的关键词
search.SearchOf("looking for this text", FoxitRDKNative.fts.FullTextSearch.e_RankHitCountASC, searchCallback);
} catch (e) {
console.error(e);
}
}
}
PauseCallbackImpl 回调的示例代码如下所示:
js
class PauseCallbackImpl extends FoxitRDKNative.common.PauseCallback {
private m_milliseconds = 0;
private m_startTime = 0;
public constructor(milliSeconds: number) {
super()
this.m_milliseconds = milliSeconds;
this.m_startTime = systemDateTime.getTime();
}
NeedToPauseNow(): boolean {
if (this.m_milliseconds < 1) {
return false;
}
const diff = systemDateTime.getTime() - this.m_startTime;
if (diff > this.m_milliseconds) {
this.m_startTime = systemDateTime.getTime();
return true;
} else {
return false;
}
}
}
MySearchCallback 回调的示例如下所示:
js
class MySearchCallback extends FoxitRDKNative.fts.SearchCallback {
public release(): void {
}
public retrieveSearchResult(filePath: string, pageIndex: number, matchResult: string, matchStartTextIndex: number,
matchEndTextIndex: number): number {
const s =
`Found file is :${filePath} \n Page index is :${pageIndex} Start text index :${matchStartTextIndex} End text index :${matchEndTextIndex} \n Match is :${matchResult} \n\n`;
console.info('MySearchCallback', 'retrieveSearchResult: ' + s);
return 0;
}
}
备注:
Foxit PDF SDK 鸿蒙版提供的全文索引搜索将以递归的方式遍历整个目录,以便搜索目录下的文件和文件夹都会被索引。
如果需要中止索引进程,可以将 pause 回调参数传递给
StartUpdateIndex
接口。其回调函数NeedToPauseNow
都会被调用,一旦完成一个 PDF 文档的索引。因此,调用者可以在回调函数NeedToPauseNow
返回 "true" 时中止索引进程。索引数据库的位置由
SetDataBasePath
接口设置。如果要清除索引数据库,请手动清除。目前,不支持从索引函数中删除指定文件相关的索引内容。SearchOf
接口的每个搜索结果都由指定的回调返回到外部。一旦SearchOf
接口返回 "true"或 "false",则表示搜索已完成。
夜间模式颜色设置
如何设置夜间模式颜色?
设置夜间模式颜色,需要首先调用 PDFViewCtrlModel#setMappingModeBackgroundColor(mappingModeBackgroundColor: number)
和PDFViewCtrlModel#setMappingModeForegroundColor(mappingModeForegroundColor: number)
接口根据您的需要设置颜色,然后使用 PDFViewCtrlModel#setColorMode(colorMode: number)
设置颜色模式。
备注:如果颜色模式已经设置为 Renderer.e_ColorModeMapping/Renderer.e_ColorModeMappingGray
,在调用 PDFViewCtrlModel#setMappingModeBackgroundColor(mappingModeBackgroundColor: number)
和 PDFViewCtrlModel#setMappingModeForegroundColor(mappingModeForegroundColor: number)
接口之后,您仍然需要再次设置。否则,颜色设置可能不会起作用。
上述接口需要在 UI Extensions 组件的源代码中调用,请将 "libs"
文件夹下的 "uiextensions"
工程添加到您的工程中。然后在 "uiextensions/src/main/ets/frame/impl/MainFrame.ets"
文件中定位到 onValueChanged
函数,根据您的需要设置颜色。
使用 UIExtensions 设置只读模式
如何使用 UIExtensions 设置只读模式?
1:接口定义
在 UIExtensionsManager 提供了以下接口:
js
/**
* whether the pdf document can be modified
*
* @return whether the pdf document can be modified
*/
public isEnableModification(): boolean
/**
* Set whether the pdf document can be modified. The default setting allows modification
*
* @param isEnabled whether the pdf document can be modified
*/
public enableModification(isEnabled: boolean): void
2: 接口使用
默认情况下没有权限控制的文档是可以编辑的。如果需要禁用编辑相关的交互功能,可以通过以下方法设置:
js
import { UIExtensionsManager } from 'uiextensions';
class EnableModificationUnit{
private uiextensionsManager:UIExtensionsManager;
constructor(uiextMgr:UIExtensionsManager) {
this.uiextensionsManager = uiextMgr;
}
private test():void{
this.uiextensionsManager.enableModification(false);
}
}
更新页面绑定 (page binding) 支持 RTL (Right-to-Left)
如何自动更新页面绑定来支持 RTL (Right-to-Left) ?
对于大多数语言,我们使用的阅读习惯都是从左往右,这需要在左边缘进行页面绑定。但是,也有一些语言的阅读习惯是从右往左,比如阿拉伯语和希伯来语以及几种东亚文字。在这种情况下,用户最好在右边缘进行页面绑定,页面将从右到左排列(第一页在最右边)。为此,我们做了从右到左的页面布局的适配。
页面绑定与水平滚动一起使用。对于垂直滚动,它仅在启用双页模式时才有效。
以编程方式更新页面绑定
Foxit PDF SDK 鸿蒙版在 PDF_PAGE_BINDING_EDGE
枚举类中定义了常量 LEFT 和 RIGHT:
- LEFT: 表示文档顺序从左往右排列
- RIGHT: 表示文档顺序从右往左排列
然后,通过如下的方法来更新页面绑定来切换页面布局:
js
import { PDFViewCtrlModel, PDF_PAGE_BINDING_EDGE } from 'foxit_rdk';
import { UIExtensionsManager } from 'uiextensions';
class PageBindingUnit {
private uiExtensionsManager: UIExtensionsManager;
private pdfviewCtrl: PDFViewCtrlModel;
constructor(uiExtMgr: UIExtensionsManager) {
this.uiExtensionsManager = uiExtMgr;
this.pdfviewCtrl = this.uiExtensionsManager.getPDFViewCtrlModel();
}
private test(): void {
this.pdfviewCtrl.setPageBinding(PDF_PAGE_BINDING_EDGE.RIGHT);
}
}
打开网页 PDF 文件的问题
如何解决使用 PDFViewCtrlModel#openDocFromUrl(url: string, password?: string, cacheOption?: FoxitRDKNative.custom.CacheOption, requestOptions?: Record<string, string>, cb?: (errorCode: FoxitRDKNative.Common.ErrorCode) => void)
接口打开网页PDF文件时,一些文档可能无法正确显示或根本无法显示的问题?
这个问题发生在一些带有大量对象的文档在加载完成之前就被关闭,导致缓存的数据不完整。在尝试加载数据时,当前没有方法来判定数据的有效性,只能判定该数据是否已经被缓存了。
为了解决这个问题,建议用户清除缓存数据,并使用以下方法重新加载文档。这种方法不会影响文档的打开速度,因为 SDK 内部是根据页码来加载网页的。
js
/**
* Clear the cache file by the specified url.
*
* @param url The url of the document that used in {@link PDFViewCtrlModel.openDocFromUrl}
* @see openDocFromUrl(string, string, CacheOption, Record<string, string>, (errorCode: FoxitRDKNative.common.ErrorCode) => void)
*/
public clearCacheFile(url: string): void
/**
* Clear all the cache files.
*
* @see openDocFromUrl(string, string, CacheOption, Record<string, string>, (errorCode: FoxitRDKNative.common.ErrorCode) => void)
*/
public clearAllCacheFiles(): void