diff --git a/lib/src/pdf_api.dart b/lib/src/pdf_api.dart index b82cec7..efa4f50 100644 --- a/lib/src/pdf_api.dart +++ b/lib/src/pdf_api.dart @@ -56,6 +56,7 @@ abstract class PdfDocumentFactory { PdfDownloadProgressCallback? progressCallback, PdfDownloadReportCallback? reportCallback, bool preferRangeAccess = false, + Map? headers, }); /// Singleton [PdfDocumentFactory] instance. @@ -222,6 +223,7 @@ abstract class PdfDocument { /// [progressCallback] is called when the download progress is updated (Not supported on Web). /// [reportCallback] is called when the download is completed (Not supported on Web). /// [preferRangeAccess] to prefer range access to download the PDF (Not supported on Web). + /// [headers] is used to specify additional HTTP headers especially for authentication/authorization. static Future openUri( Uri uri, { PdfPasswordProvider? passwordProvider, @@ -229,6 +231,7 @@ abstract class PdfDocument { PdfDownloadProgressCallback? progressCallback, PdfDownloadReportCallback? reportCallback, bool preferRangeAccess = false, + Map? headers, }) => PdfDocumentFactory.instance.openUri( uri, @@ -237,6 +240,7 @@ abstract class PdfDocument { progressCallback: progressCallback, reportCallback: reportCallback, preferRangeAccess: preferRangeAccess, + headers: headers, ); /// Pages. diff --git a/lib/src/pdf_file_cache.dart b/lib/src/pdf_file_cache.dart index 61688c9..f0d9209 100644 --- a/lib/src/pdf_file_cache.dart +++ b/lib/src/pdf_file_cache.dart @@ -315,6 +315,7 @@ Future pdfDocumentFromUri( PdfDownloadProgressCallback? progressCallback, PdfDownloadReportCallback? reportCallback, bool useRangeAccess = true, + Map? headers, }) async { final startTime = reportCallback != null ? DateTime.now() : null; void report() { @@ -334,13 +335,8 @@ Future pdfDocumentFromUri( if (!cache.isInitialized) { cache.setBlockSize(blockSize ?? PdfFileCache.defaultBlockSize); final result = await _downloadBlock( - httpClient, - uri, - cache, - progressCallback, - 0, - useRangeAccess: useRangeAccess, - ); + httpClient, uri, cache, progressCallback, 0, + useRangeAccess: useRangeAccess, headers: headers); if (result.isFullDownload) { return await PdfDocument.openFile( cache.filePath, @@ -355,8 +351,14 @@ Future pdfDocumentFromUri( // cache is valid; no need to download. } else { final result = await _downloadBlock( - httpClient, uri, cache, progressCallback, 0, - addCacheControlHeaders: true); + httpClient, + uri, + cache, + progressCallback, + 0, + addCacheControlHeaders: true, + headers: headers, + ); if (result.isFullDownload) { cache.close(); // close the cache file before opening it. httpClient.close(); @@ -379,7 +381,13 @@ Future pdfDocumentFromUri( final isAvailable = cache.isCached(blockId); if (!isAvailable) { await _downloadBlock( - httpClient, uri, cache, progressCallback, blockId); + httpClient, + uri, + cache, + progressCallback, + blockId, + headers: headers, + ); } final readEnd = min(p + size, (blockId + 1) * cache.blockSize); final sizeToRead = readEnd - p; @@ -435,6 +443,7 @@ Future<_DownloadResult> _downloadBlock( int blockCount = 1, bool addCacheControlHeaders = false, bool useRangeAccess = true, + Map? headers, }) async { int? fileSize; final blockOffset = blockId * cache.blockSize; @@ -447,6 +456,7 @@ Future<_DownloadResult> _downloadBlock( if (useRangeAccess) 'Range': 'bytes=$blockOffset-${end - 1}', if (addCacheControlHeaders) ...cache.cacheControlState.getHeadersForFetch(), + if (headers != null) ...headers, }, ) ..sink.close(), diff --git a/lib/src/pdfium/pdfrx_pdfium.dart b/lib/src/pdfium/pdfrx_pdfium.dart index 139cd2e..0283d36 100644 --- a/lib/src/pdfium/pdfrx_pdfium.dart +++ b/lib/src/pdfium/pdfrx_pdfium.dart @@ -226,6 +226,7 @@ class PdfDocumentFactoryImpl extends PdfDocumentFactory { PdfDownloadProgressCallback? progressCallback, PdfDownloadReportCallback? reportCallback, bool preferRangeAccess = false, + Map? headers, }) => pdfDocumentFromUri( uri, @@ -234,6 +235,7 @@ class PdfDocumentFactoryImpl extends PdfDocumentFactory { progressCallback: progressCallback, reportCallback: reportCallback, useRangeAccess: preferRangeAccess, + headers: headers, ); static bool _isPasswordError({int? error}) { diff --git a/lib/src/web/pdf.js.dart b/lib/src/web/pdf.js.dart index 8bf2538..fa424d0 100644 --- a/lib/src/web/pdf.js.dart +++ b/lib/src/web/pdf.js.dart @@ -37,7 +37,7 @@ extension type _PdfjsDocumentInitParameters._(JSObject _) implements JSObject { external _PdfjsDocumentInitParameters({ String? url, JSArrayBuffer? data, - JSObject httpHeaders, + JSAny? httpHeaders, bool? withCredentials, String? password, int? length, @@ -49,7 +49,7 @@ extension type _PdfjsDocumentInitParameters._(JSObject _) implements JSObject { external String? get url; external JSArrayBuffer? get data; - external JSObject get httpHeaders; + external JSAny? get httpHeaders; external bool? get withCredentials; external String? get password; external int? get length; @@ -66,13 +66,23 @@ extension type _PDFDocumentLoadingTask(JSObject _) implements JSObject { external JSPromise get promise; } -Future pdfjsGetDocument(String url, {String? password}) => +Future pdfjsGetDocument( + String url, { + String? password, + Map? headers, + bool withCredentials = false, +}) => _pdfjsGetDocument( _PdfjsDocumentInitParameters( url: url, password: password, + httpHeaders: headers?.jsify(), + withCredentials: withCredentials, cMapUrl: PdfJsConfiguration.configuration?.cMapUrl ?? _pdfjsCMapUrl, cMapPacked: PdfJsConfiguration.configuration?.cMapPacked ?? true, + useSystemFonts: PdfJsConfiguration.configuration?.useSystemFonts, + standardFontDataUrl: + PdfJsConfiguration.configuration?.standardFontDataUrl, ), ).promise.toDart; @@ -84,6 +94,9 @@ Future pdfjsGetDocumentFromData(ByteBuffer data, password: password, cMapUrl: PdfJsConfiguration.configuration?.cMapUrl, cMapPacked: PdfJsConfiguration.configuration?.cMapPacked, + useSystemFonts: PdfJsConfiguration.configuration?.useSystemFonts, + standardFontDataUrl: + PdfJsConfiguration.configuration?.standardFontDataUrl, ), ).promise.toDart; diff --git a/lib/src/web/pdf_js_configuration.dart b/lib/src/web/pdf_js_configuration.dart index 13082b0..b1a50f0 100644 --- a/lib/src/web/pdf_js_configuration.dart +++ b/lib/src/web/pdf_js_configuration.dart @@ -7,6 +7,8 @@ class PdfJsConfiguration { required this.workerSrc, required this.cMapUrl, required this.cMapPacked, + this.useSystemFonts = true, + this.standardFontDataUrl, this.pdfJsDownloadTimeout = const Duration(seconds: 10), }); @@ -19,10 +21,17 @@ class PdfJsConfiguration { /// `cmaps` directory URL such as https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/cmaps/ final String cMapUrl; - /// Whether to use the packed cmaps. Default is true. + /// Whether to use the packed cmaps. The default is true. final bool cMapPacked; - /// The timeout for downloading the PDF.js library. Default is 10 seconds. + /// When true, fonts that aren't embedded in the PDF document will fallback to a system font. + /// The default is true. + final bool useSystemFonts; + + /// The URL where the standard font files are located. Include the trailing slash. + final String? standardFontDataUrl; + + /// The timeout for downloading the PDF.js library. The default is 10 seconds. final Duration pdfJsDownloadTimeout; /// The current configuration. null to use the default. diff --git a/lib/src/web/pdfrx_web.dart b/lib/src/web/pdfrx_web.dart index 214241b..78b108e 100644 --- a/lib/src/web/pdfrx_web.dart +++ b/lib/src/web/pdfrx_web.dart @@ -82,17 +82,16 @@ class PdfDocumentFactoryImpl extends PdfDocumentFactory { String filePath, { PdfPasswordProvider? passwordProvider, bool firstAttemptByEmptyPassword = true, - }) async { - return _openByFunc( - (password) => pdfjsGetDocument( - filePath, - password: password, - ), - sourceName: filePath, - passwordProvider: passwordProvider, - firstAttemptByEmptyPassword: firstAttemptByEmptyPassword, - ); - } + }) => + _openByFunc( + (password) => pdfjsGetDocument( + filePath, + password: password, + ), + sourceName: filePath, + passwordProvider: passwordProvider, + firstAttemptByEmptyPassword: firstAttemptByEmptyPassword, + ); @override Future openUri( @@ -102,9 +101,15 @@ class PdfDocumentFactoryImpl extends PdfDocumentFactory { PdfDownloadProgressCallback? progressCallback, PdfDownloadReportCallback? reportCallback, bool preferRangeAccess = false, + Map? headers, }) => - openFile( - uri.toString(), + _openByFunc( + (password) => pdfjsGetDocument( + uri.toString(), + password: password, + headers: headers, + ), + sourceName: uri.toString(), passwordProvider: passwordProvider, firstAttemptByEmptyPassword: firstAttemptByEmptyPassword, );