2016-05-23 1 views
2

Я использую плагин для создания изображений (cordova-imagePicker), чтобы получать изображения из галереи и загружать их на сервер.Кордова - Чтение Большое изображение corrupts image

Я использую Кордову 6.1.1 с Android платформы 5.1.1 и следующих модулей:

cordova-plugin-camera 2.2.0 "Camera" 
cordova-plugin-compat 1.0.0 "Compat" 
cordova-plugin-device 1.0.1 "Device" 
cordova-plugin-file 4.2.0 "File" 
cordova-plugin-imagepicker 1.1.0 "ImagePicker" 
cordova-plugin-inappbrowser 1.4.0 "InAppBrowser" 
cordova-plugin-media 2.3.0 "Media" 

В обратном вызове плагина, я уверен, преобразование пути я получаю в файл, используя следующий код. Обратите внимание, что я использую resolveFile, потому что этот код работает и на рабочем столе, и в этом случае запись уже является файлом.

var resolveFile = function(entry) { 
    if (typeof(entry) === "string") { 
     var deferred = $q.defer(); 
     // first convert to local file system URL 
     window.resolveLocalFileSystemURL(entry, function(fileEntry) { 
      // now read/convert the file to file object. 
      fileEntry.file(function(file) { 
       console.log("File converted to file entry"); 
       deferred.resolve(file); 
      }, function(err) { 
       console.log("Failed to convert to file entry", err); 
       deferred.reject(err); 
      }); 
     }, function(err) { 
      console.log("Failed to resolve to file URL", err); 
      deferred.reject(err); 
     }); 

     return deferred.promise; 
    } else { 
     return $q.when(entry); 
    } 
}; 

Это, в свою очередь, используется для считывания изображения и передать его в функцию, которая загружает его на сервер ($files это то, что я получаю от плагина или от входа в случае настольного/браузера):

var upload = function() { 
    if (!$files[currentFile]) { 
     onAllFinished(); 
     return; 
    } 
    file = $files[currentFile]; 
    beforeLoad(file); 
    fileReader = new FileReader(); 
    fileReader.onload = onload; 
    fileReader.onprogress = progress; 
    resolveFile(file).then(function(actualFile) { 
     fileReader.readAsDataURL(actualFile); 
    }); 
    currentFile++; 
}; 

в вышеприведенном OnLoad вырезает данные изображения (следуя «base64» в строке) и отправляет его в коде загрузки, которая ожидает строку base64 и загружает данные на сервер с помощью простого AJAX вызова:

var uploadPhoto = function(url, photo, callback, error) 
    $http.post(url, { 
     photo: photo, 
    }) 
    .success(callback) 
    .error(function (data, status, headers, config) { 
     if (error) 
      error(data, status, headers, config); 
    }); 

Последняя функция работает также с плагином камеры camera plugin с использованием DATA_URI цели (я знаю, это не рекомендуется), которые также возвращают строку base64 (так что я могу повторно использовать код).

Мне кажется, что что-то не так происходит с выходом для чтения файлов (я предполагаю). Что (я думаю) намекает на то, что маленькие изображения (10s kb) загружаются как хорошо, так и уже подготовленные base64 строки из плагина камеры, но большие изображения (несколько МБ), которые проходят через filereader (на Android, на рабочем столе это прекрасно) загружаются поврежденными (см. ниже).

Кто-нибудь сталкивался с такими проблемами? Может ли кто-нибудь предложить исправление (кроме изменения кода для использования плагина FileTransfer)?

Исходное изображение:

original (almost, had to shrink it for upload to SO)

Загруженный (поврежден) изображение. Обратите внимание, некоторые из них читают/закачано отлично:

Uploaded to server after reading through FileReader

ответ

9

Я нашел ваш вопрос при поиске решения аналогичной задачи. DataURL больших изображений с камеры будет отображаться при использовании в качестве источника изображения, но тот же образ поврежден, когда я использую fileReader.readAsDataURL.

Я смог обойти проблему, используя fileReader.readAsBinaryData вместо fileReader.readAsDataURL, а затем превратив двоичную строку в dataURL.

window.resolveLocalFileSystemURL(imageUri, function done(fileEntry) { 
    fileEntry.file(function (fileObj) { 
     var image = new Image(); 
     var reader = new FileReader(); 
     reader.onloadend = function (e) { 
      image.src = "data:image/jpeg;base64," + window.btoa(e.target.result) 
     } 
     reader.readAsBinaryString(fileObj); 
    } 
} 

Надеюсь, это поможет вам найти обходное решение.

+0

Это выглядит многообещающим. Я постараюсь проверить это. В любом случае я решил переключиться на работу с файлами FILE_URI и FileTransfer. Это влечет за собой изменение и моей серверной части, но это рекомендуемый способ и похоже на более безопасный подход. –

+0

Привет, это отлично работает. Теперь я не уверен, использовать ли FILE_URI/FileTransfer плагин или нет :). Благодаря! –

+0

Добро пожаловать. –