Ошибка JSONStore при отправке коллекции с документами с файлами

У меня есть JSONStore для списка клиентов, пользователь может добавлять документы для этих клиентов с помощью приложения.

Список клиентов и его данные (также прилагаемые документы) должны быть синхронизированы с серверной частью.

Когда я добавляю документ ppt 774 КБ (это размер в двоичном виде, я преобразую его в base64) в хранилище json и выполняю push(), он завершается с ошибкой:

E/CursorWindow(32705): need to grow: mSize = 1048576, size = 1056310, freeSpace() = 1048464, numRows = 1
E/CursorWindow(32705): Attempting to grow window beyond max size (1048576)
E/Cursor(32705): Failed allocating 1056310 bytes for text/blob at 0,1
D/Cursor(32705): finish_program_and_get_row_count row 0
E/CursorWindow(32705): need to grow: mSize = 1048576, size = 1056310, freeSpace() = 1048464, numRows = 1
E/CursorWindow(32705): Attempting to grow window beyond max size (1048576)
E/Cursor(32705): Failed allocating 1056310 bytes for text/blob at 0,1
D/Cursor(32705): finish_program_and_get_row_count row 0
E/CursorWindow(32705): Bad request for field slot 0,0. numRows = 0, numColumns = 4
E/jsonstore-core(32705): error while dispatching action "allDirty"
E/jsonstore-core(32705): java.lang.IllegalStateException: get field slot from row 0 col 0 failed
E/jsonstore-core(32705):    at net.sqlcipher.CursorWindow.getLong_native(Native Method)
E/jsonstore-core(32705):    at net.sqlcipher.CursorWindow.getLong(CursorWindow.java:381)
E/jsonstore-core(32705):    at net.sqlcipher.AbstractWindowedCursor.getLong(AbstractWindowedCursor.java:110)
E/jsonstore-core(32705):    at net.sqlcipher.AbstractCursor.moveToPosition(AbstractCursor.java:195)
E/jsonstore-core(32705):    at net.sqlcipher.AbstractCursor.moveToNext(AbstractCursor.java:257)
E/jsonstore-core(32705):    at android.database.CursorWrapper.moveToNext(CursorWrapper.java:166)
E/jsonstore-core(32705):    at com.worklight.androidgap.plugin.storage.AllDirtyActionDispatcher$AllDirtyAction.performAction(AllDirtyActionDispatcher.java:148)
E/jsonstore-core(32705):    at com.worklight.androidgap.plugin.storage.AllDirtyActionDispatcher$AllDirtyAction.performAction(AllDirtyActionDispatcher.java:119)
E/jsonstore-core(32705):    at com.worklight.androidgap.plugin.storage.DatabaseActionDispatcher$Context.performReadableDatabaseAction(DatabaseActionDispatcher.java:141)
E/jsonstore-core(32705):    at com.worklight.androidgap.plugin.storage.AllDirtyActionDispatcher.dispatch(AllDirtyActionDispatcher.java:64)
E/jsonstore-core(32705):    at com.worklight.androidgap.plugin.storage.DatabaseActionDispatcher.dispatch(DatabaseActionDispatcher.java:56)
E/jsonstore-core(32705):    at com.worklight.androidgap.plugin.storage.BaseActionDispatcher.dispatch(BaseActionDispatcher.java:87)
E/jsonstore-core(32705):    at com.worklight.androidgap.plugin.storage.DispatchingPlugin$ActionDispatcherRunnable.run(DispatchingPlugin.java:113)
E/jsonstore-core(32705):    at com.worklight.androidgap.plugin.storage.DispatchingPlugin$SerialExecutor$1.run(DispatchingPlugin.java:147)
E/jsonstore-core(32705):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
E/jsonstore-core(32705):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
E/jsonstore-core(32705):    at java.lang.Thread.run(Thread.java:856)
E/myApp (32705): [wl.jsonstore] {"src":"push","err":8,"msg":"FAILED_TO_GET_UNPUSHED_DOCUMENTS_FROM_DB","col":"Documentos","usr":"jsonstore","doc":{},"res":{}}

Я могу добавить документ, ошибка при выполнении метода push().

Вся информация, которую я видел в stackru и инфоцентре о JSONStore, заключается в том, что ограничения по размеру нет. У меня более чем достаточно свободного места в моем мобильном телефоне.

Любая идея?

Спасибо.

1 ответ

Решение

"Не храните большие двоичные объекты [...] в своей базе данных. Храните идентификаторы в своей базе данных и помещайте большие двоичные объекты как файлы в хранилище". - Источник

У Cordova есть File API, который вы можете использовать.

Вот быстрый пример:

//Code to write customer-1-file1.ppt and customer-1-file2.ppt to disk.
//See Cordova's File API.

//Pseudocode to get the blobsCollection and add metadata to be able to find the files.
//This would be inside the success callback for writing the files.
WL.JSONStore.get('blobsCollection')
  .add([{fileName: 'customer-1-file1.ppt'}, {fileName: 'customer-1-file2.ppt'}]);

//Some time has passed...

//Pseudocode to get %customer-1% from disk
//% are wildcards characters and match any string
WL.JSONStore.get('blobsCollection')
  .find({fileName: 'customer-1'}, {exact: false})
  .then(function (listOfFiles) {
    //listOfFiles => [{_id: 1, json: { fileName: 'customer-1-file1.ppt'} }, 
    //                {_id: 2, json: { {fileName: 'customer-1-file2.ppt'} }]

    var firstFile = listOfFiles[0].json.fileName;

    //Code to read firstFile. See Cordova's File API.
  });

JSONStore поддерживается SQLite (ну, технически SQLCipher, который является оберткой для SQLite, которая добавляет шифрование данных). Чтение внутренних и внешних BLOB-объектов в SQLite. Вывод: "Для больших двоичных объектов размером менее 100 КБ чтение выполняется быстрее, когда большие двоичные объекты сохраняются непосредственно в файле базы данных. Для больших двоичных объектов размером более 100 КБ чтение из отдельного файла выполняется быстрее ".

Если вам нужно хранить большие двоичные объекты, размер которых превышает размер курсора SQLite по умолчанию (1048576 байт), я предлагаю запрос функции здесь.

Я удостоверюсь, что это упомянуто в документации.

Обратите внимание, что есть API-интерфейс getPushRequired, который вы можете использовать для получения списка документов, которые push API попытается отправить на адаптер Worklight. Вам нужно будет отправить изменения файла самостоятельно в Worklight Adapter, используя WL.Client.invokeProcedure или непосредственно к бэкэнду, используя что-то вроде jQuery.ajax,

Другие вопросы по тегам