Skip to main content

Storage for Pages | React Native Document Scanner

Storage

Since version 3.0 of this module the native Scanbot SDKs use the internal and secure storage locations for all produced files (JPG, PNG, PDF, TIFF, etc) by default.

  • On Android all files will be stored in the internal files directory of your application. No permissions are required for your app to read or write files in this directory.

  • On iOS all files will be stored in the Application Support folder of your application.

Customize Storage Location

It is strongly recommended to use the default storage location. However, you can override the storage directory on initialization of the SDK Module. The initializeSdk method can take an optional parameter storageBaseDirectory to set a custom storage location.

const options = {
storageBaseDirectory: 'file:///some/custom/storage-dir/',
...
};

const result = await ScanbotSDK.initializeSDK(options);

The value of the storageBaseDirectory must be a file URL ('file:///...) pointing to a valid platform-specific file system path. If this directory does not exist yet, the SDK Module will try to create it. To work with the file system we recommend the npm module react-native-fs

For the full demo code please check out our example app scanbot-sdk-example-react-native.

⚠️ Note: When overriding the default storage location, make sure

  • you have implemented a suitable storage permissions request handling on Android
  • you fully understand the consequences regarding the accessibility (security) of the produced document files.

👉 For more details about the storage locations on Android and iOS please also see:

Storage Cleanup

There is no automatic file clean mechanism in this SDK Module, because only your App can decide when the perfect time is to remove the files produced by this SDK (images, PDFs, etc).

To avoid storage space issues caused by too many produced image files, it is strongly recommended to implement a suitable cleanup functionality based on the requirements of your app. This SDK Module provides the following helper methods to keep the storage clean:

  • removePage method to delete a certain Page object with all its files.
  • cleanup method to remove all generated files by this RN SDK Module (scanned and imported images, export files like PDF, TIFF, etc).

Storage Encryption

The Scanbot SDK provides the ability to store the generated image files (JPG, PNG) and PDF files encrypted. This feature provides an additional level of security to the default secure storage locations of the native SDKs.

By default the file encryption is disabled. To enable it you have to pass the following config parameters on SDK initialization:

  • fileEncryptionPassword: A secure password or passphrase to derive the AES key for encryption/decryption.
  • fileEncryptionMode: Encryption mode, AES128 or AES256 (default and recommended).
const options: InitializationOptions = {
fileEncryptionPassword: 'SomeSecretPa$$w0rdForFileEncryption',
fileEncryptionMode: 'AES256'
};
await ScanbotSDK.initializeSDK(options);

By activating the storage encryption the native Scanbot SDKs will use the built-in AES 128 or AES 256 encryption. All generated image files (JPG, PNG) including the preview image files, as well as the exported PDF files will be encrypted in memory and stored as encrypted data files on the flash storage of the device.

The Scanbot SDK derives the AES key from the given password, an internal salt value, and the internal number of iterations using the PBKDF2 function.

When applying image operations like cropping, rotation or image filters, the Scanbot SDK will decrypt the image file in memory, apply the changes, encrypt and store it again.

Handle Encrypted Images

Display Encrypted Images

If the file encryption is enabled you will not be able to display preview images via file URIs (e.g. page.documentPreviewImageFileUri). Instead, you have to load the decrypted data of a preview image and use it for displaying an image. In order to do this use the API function getImageData(imageFileUri: string):

// use the low-res image "documentPreviewImageFileUri" for the preview:
const result = await ScanbotSDK.getImageData(page.documentPreviewImageFileUri);
const decryptedImageDataAsBase64 = `data:image/jpeg;base64,${result.base64ImageData}`;
...
<Image source={uri: decryptedImageDataAsBase64} style={...} />

👉 For a full implementation see our example app.

Upload Encrypted Images

To upload an image you have the following options:

1) Use the encrypted image file to upload to your server and decrypt it in the backend. Please contact our team to get support on how to generate the corresponding AES key and decrypt images on your backend.

2) Alternatively, get the decrypted image data as Base64 on the mobile device by using the getImageData(imageFileUri: string) function and use this data for the upload process:

// use the final hi-res image "documentImageFileUri" for the upload process:
const result = await ScanbotSDK.getImageData(page.documentImageFileUri);
const decryptedImageDataAsBase64 = result.base64ImageData;
yourCustomUploadFunction(decryptedImageDataAsBase64);

Ready-To-Use UI

Configuration

Settings controlling color are expected to be passed as strings in the '#RRGGBB' format.

Pages

The Scanbot SDK provides a ready-to-use UI for document scanning and cropping. Both components use the notion of a 'page' as a data model for the scanning and cropping activities. A Page object has the following fields:

interface Page {
pageId: string;
polygon: Point[];
detectionResult: DetectionStatus;
pageImageSource: PageImageSource;
filter: ImageFilter;
documentImageSizeLimit?: Size;
originalImageFileUri: string;
documentImageFileUri?: string;
originalPreviewImageFileUri: string;
documentPreviewImageFileUri?: string;
}

The fields are:

  • pageId - a string identifying the page in the internal page file storage
  • polygon - the page's cropping polygon as calculated by a document detection operation or as set by the cropping UI. Modifying the polygon will change the polygon as shown in the cropping UI but will not automatically re-crop the original image
  • detectionResult - the detection result of the document detection operation that produced the page (either the document scanner or detectDocument())
  • pageImageSource - The PageImageSource (MANUAL_SNAP, AUTO_SNAP, CAMERA_FRAME) or UNKNOWN if the image has been imported or the source is unknown.
  • filter - The Image Filter that was applied on the page image
  • documentImageSizeLimit - The value that was set for documentImageSizeLimit, which limits the maximum size of the document image.
  • originalImageFileUri - file URI of the original image
  • documentImageFileUri - file URI of the cropped document image (if document detection was successful)
  • originalPreviewImageFileUri - file URI of a screen-sized preview of the original image
  • documentPreviewImageFileUri - file URI of a screen-sized preview of the document image

Pages are stored in an internal page file storage, where the pageId serves as a name prefix for the stored image files. Operations that modify pages work in-place. That is, for example, rotatePage() overwrites the page's image files with their rotated versions. This behavior differs from the behavior of raw image functions like rotateImage(), which always create a new file. All URI properties of a page have a ?minihash= query parameter appended to them with the hash of a portion of the image file. Different images will almost always have a different hash and therefore a different URI, which will force the WebView to reload the page's images when changed.

Note

Some React Native libraries/functions (e.g. RNFetchBlob and RNFS.readFile()) are unable to properly handle file URIs. Instead, they require a file path. Our SDK returns file URIs. Here is an iOS example:

  • File URI: file:///var/.../PageFileStorage/JPEG/documents/BFF43CCC-1EF4-4936-9D99-A22871FDCFE2.jpg?minihash=4acbb92e71901fd71fff989c38d1d890
  • The corresponding pure file path: /var/.../PageFileStorage/JPEG/documents/BFF43CCC-1EF4-4936-9D99-A22871FDCFE2.jpg

Note that the file:// protocol has some optional query arguments (?minihash=) as well as whitespace encoding (%20) in the file URI.

The solution is to convert the file URI to a path, like this:

const fileUriToPath = (fileUri: string) => decodeURI(fileUri
.replace('file://', '')
.replace(/\?minihash=.*$/, '')
);

Persistence of Page Objects

Scanbot SDK does not persist page objects, only the image files (.jpg or .png). The management of page objects and the persistence of the page metadata is left to the app. Depending on the use case, it may be necessary to persist the data of the page objects in the app (e.g. as JSON in a local SQLite database). If this is the case, the following must be considered.

The Page objects contain absolute paths to the image files:

{
"pageId": "60426F47-4119-48F8-ADA9-F7E60D583CB4",
"filter": "NONE",
"detectionResult": "OK",
"polygon": [{"x":0.17427248677248677,"y":0.1212797619047619},{"x":0.8604497354497355,"y":0.13120039682539678},{"x":0.8349867724867724,"y":0.9729662698412699},{"x":0.12202380952380967,"y":0.9471726190476191}],
"documentPreviewImageFileUri": "file:///var/mobile/Containers/Data/Application/54286F82-A8F7-4850-A684-8D3487726A4D/Library/Application%20Support/net.doo.ScanbotSDK/SBSDK_ImageStorage_Default/PageFileStorage/JPEG/documents/60426F47-4119-48F8-ADA9-F7E60D583CB4_preview.jpg?minihash=a236a8ba5510cd0f4e88bd2045f52c4e",
"originalImageFileUri": "file:///var/mobile/Containers/Data/Application/54286F82-A8F7-4850-A684-8D3487726A4D/Library/Application%20Support/net.doo.ScanbotSDK/SBSDK_ImageStorage_Default/PageFileStorage/JPEG/originals/60426F47-4119-48F8-ADA9-F7E60D583CB4.jpg?minihash=4e9f0446421343eaaa1e415fdb446a12",
"originalPreviewImageFileUri": "file:///var/mobile/Containers/Data/Application/54286F82-A8F7-4850-A684-8D3487726A4D/Library/Application%20Support/net.doo.ScanbotSDK/SBSDK_ImageStorage_Default/PageFileStorage/JPEG/originals/60426F47-4119-48F8-ADA9-F7E60D583CB4_preview.jpg?minihash=da888cd42db07e52b15a6ada29a37b63",
"documentImageFileUri": "file:///var/mobile/Containers/Data/Application/54286F82-A8F7-4850-A684-8D3487726A4D/Library/Application%20Support/net.doo.ScanbotSDK/SBSDK_ImageStorage_Default/PageFileStorage/JPEG/documents/60426F47-4119-48F8-ADA9-F7E60D583CB4.jpg?minihash=f9aab62cc37fec555abe94c83406a1b3"
}

The page image files are stored in corresponding storage locations - also see the Storage section. By default, the Scanbot SDK Android uses the internal files directory of the app, whereas the Scanbot SDK iOS uses the "Application Support" folder. Those storage folders are secure and are not affected by an app update.

However, on iOS, the absolute file path of the "Application Support" folder is not reliable. For each fresh install of an app, a new UUID is generated, in the following format: /var/mobile/Containers/Data/Application/{UUID}. That is where application data is stored. When updating the app, the uuid may change. For example:

Before an app update:

file:///var/mobile/Containers/Data/Application/54286F82-A8F7-4850-A684-8D3487726A4D/Library/Application%20Support/net.doo.ScanbotSDK/SBSDK_ImageStorage_Default/PageFileStorage/JPEG/documents/60426F47-4119-48F8-ADA9-F7E60D583CB4.jpg

After the app update:

file:///var/mobile/Containers/Data/Application/C9181555-252A-4665-892F-793008ED0EDD/Library/Application%20Support/net.doo.ScanbotSDK/SBSDK_ImageStorage_Default/PageFileStorage/JPEG/documents/60426F47-4119-48F8-ADA9-F7E60D583CB4.jpg

Please note that the actual image files are still there, only the absolute file paths change.

To get to the new absolute paths, the API method refreshImageUris({pages: Page []}) has been introduced in the plugin version 4.4.0. Please use this method to refresh all image file URIs from affected pages:

const result = await ScanbotSDK.refreshImageUris({pages: loadedPages});
const refreshedPages = result.pages;

It is highly recommended using this method whenever you have to (re-)load JSON Page objects from the database of your app, regardless of whether there was an app update or not.

Cleanup

ScanbotSDK.cleanup(): Promise

By calling ths function all temporary output files generated by the Scanbot SDK module will be deleted.

Page Operations

ScanbotSdk.createPage(imageUri: string): Promise<Page>

Creates a page from an image (presumably the image of an uncropped document).

Returns

The promise resolves to a page object. As the page has not been cropped yet, the documentImageFileUri and documentPreviewImageFileUri properties will be empty.

ScanbotSdk.setDocumentImage(page: Page, imageUri: string): Promise<Page>

Replaces the document image of a page. The passed image file will be copied into the internal page file storage.

  • page - the page to modify.
  • imageUri - the URI of an image file with which to overwrite the page's document image.

Returns

The promise resolves to a page object with the replaced document image.

ScanbotSdk.detectDocumentOnPage(page: Page): Promise<Page>

Runs document detection on the original image of the given page. The detection status, polygon and cropped document image are returned as a new page object in the returned promise.

ScanbotSdk.applyImageFilterOnPage(page: Page, filter: ImageFilter): Promise<Page>

Applies a filter to the unfiltered document image of a page.

  • page - the page to filter.
  • imageFilter - the image filter to apply. The special value 'NONE' will remove any previously applied filter from the document image.

ScanbotSdk.getFilteredDocumentPreviewUri(page: Page, imageFilter: ImageFilter): Promise<string>

Creates a preview image of a filter applied onto the document of a page. Does not modify the document image of the passed page.

  • page - the page for which to create a filtered document preview.
  • imageFilter - the image filter to apply. The special value 'NONE' will remove any previously applied filter from the document image.

Returns

A file URI with the preview image of the filtered document page.

ScanbotSdk.rotatePage(page: Page, times: number)

Rotates a page counter-clockwise in increments of 90 degrees.

  • page - the page to rotate.
  • times - the number of counter-clockwise 90 degree rotations to apply.

ScanbotSdk.removePage(page: Page): Promise

Removes all images of a page from the file storage.

Want to scan longer than one minute?

Generate your free "no-strings-attached" Trial License and properly test the Scanbot SDK.

Get your free Trial License

What do you think of this documentation?