Подтвердить что ты не робот

Как сохранить и получить изображение на localStorage?

Думал, что у меня это было, но нет. Цель: привязать фотографию (страховую карточку), сохранить ее локально и получить позже.

// Get a reference to the image element
var elephant = document.getElementById("SnapIt_mobileimage_5");

var imgCanvas = document.createElement("canvas"),
imgContext = imgCanvas.getContext("2d");

// Make sure canvas is as big as the picture
imgCanvas.width = elephant.width;
imgCanvas.height = elephant.height;

// Draw image into canvas element

imgContext.drawImage(elephant, 0, 0, elephant.width, elephant.height );
 console.log( 'Did that' );
// Get canvas contents as a data URL
var imgAsDataURL = imgCanvas.toDataURL("data:image/jpg;base64,");

// Save image into localStorage
try {
localStorage.setItem("elephant", imgAsDataURL);
}
catch (e) {
console.log("Storage failed: " + e);
}; 

//Did it work?
var pic = localStorage.getItem("elephant");

console.log( elephant );
console.log( pic );

Каждый шаг выполняется успешно, конечный результат:

<img id="SnapIt_mobileimage_5" class=" SnapIt_mobileimage_5" name="mobileimage_5" dsid="mobileimage_5" src="files/views/assets/image/IMG_0590.JPG">
 data:image/png;base64,iVBORw0KGgoAAAANSUhEUgA

На новой странице, когда я спрашиваю

var policy_shot = localStorage.getItem( 'elephant' );
console.log( policy_shot );

$('#TestScreen_mobileimage_1').src = policy_shot ;

Он записывает двоичный файл:

data:image/png;base64,iVBORw0KGgoAAAANSUhEUg ....

Но изображение не появляется.

  • Есть ли более простой подход?
  • Почему getItem (двоичный), которому предшествуют данные: image/png; вместо данных: image/jpg?
  • Вот почему он не отображается, или я делаю что-то еще не так?
4b9b3361

Ответ 1

1) Это единственный способ конвертировать изображение в строку локально (с использованием файлов FileReader, см. ниже). Для этого вам необходимо использовать сервер.

2) Чтобы получить изображение в формате JPEG, вам нужно использовать такой аргумент:

var datauri = imgCanvas.toDataURL("image/jpeg", 0.5); //0.5 = optional quality

не используйте data:... в аргументе, так как это будет недействительным, и оно выдает PNG по умолчанию, как вы можете видеть в своем результате. toDataURL() может принимать только тип, т.е. image/png, image/jpeg и т.д.

3)

Внешние файлы

Если ваше изображение было загружено из другого источника (схема, сервер...) или с помощью локальных файлов с ссылками (file://, /my/path/ и т.д.), CORS запускает и предотвратит создание данных-uri, то есть: изображение будет пустым (и, следовательно, невидимым).

Для внешних серверов вы можете запросить разрешение на использование изображения из кросс-начала, предоставив свойство crossOrigin:

<img src="http://extrernalserver/...." crossOrigin="anonymous" />

или по коду (img.crossOrigin = 'anonymous';) перед установкой src.

Тем не менее, сервер может разрешить или отклонить запрос.

Если он по-прежнему не работает, вам нужно будет загрузить изображение через прокси (f.ex. страница на вашем сервере, которая может загружать и изображение извне и обслуживать ее с вашего собственного сервера).

Или, если у вас есть доступ к конфигурации сервера, вы можете добавить заголовки разрешений доступа (Access-Control-Allow-Origin: *, см. ссылку ниже для более подробной информации).

CORS (Совместное использование ресурсов для перекрестных ссылок) является механизмом безопасности и не может работать иначе, чем эти способы.

Локальные файлы

Для локальных файлов вам нужно будет использовать FileReader - это может оказаться преимуществом, поскольку FileReader поставляется с удобным способом: readAsDataURL(). Это позволяет вам "загружать" файл изображения напрямую в виде данных-uri, не перемещаясь по холсту.

См. примеры здесь:
https://developer.mozilla.org/en-US/docs/Web/API/FileReader

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

Заключение

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

Вы можете проверить, проверив длину до и после сохранения строки, чтобы увидеть, была ли она разрезана:

console.log(imgAsDataURL.length);
... set / get ...
console.log(pic.length);

Другие возможности:

  • Элемент изображения не определен правильно.
  • Ошибка в браузере
  • Ошибка в структуре

(Я думаю, что я рассмотрел большинство типичных ловушек?)

Обновить (пропущенный, тип..; -p)

OP нашел конкретное в структуре, которое я буду здесь включать для дальнейшего использования:

В конце концов, проблема была в $('#TestScreen_mobileimage_1').src = policy_shot ; Я использую Appery.io, и они не поддерживают .src.

It $('#TestScreen_mobileimage_1').attr("src", policy_shot ) ;

Последнее примечание: localStorage очень ограничен в отношении хранения изображений. Типичное пространство для хранения составляет 2,5 - 5 мб. Каждый хранимый char занимает 2 байта, а сохранение данных-uri, закодированных как base-64, на 33% больше, чем оригинал, поэтому пространство будет скудным. Посмотрите на индексированные DB, Web SQL или File API для хороших альтернатив.

Ответ 2

Здесь полное решение, использующее File Api

    <html>
    <body>
    <input type="file" id="image-input" />
    <img id="image-container" />
    <script type="text/javascript">
    (function(){
          /** @type {Node} */
      var imgInput = document.getElementById( "image-input" ),
          /** @type {Node} */
          imgContainer = document.getElementById( "image-container" ),
          /** Restore image src from local storage */
          updateUi = function() {
            imgContainer.src = window.localStorage.getItem( "image-base64" );
          },
          /** Register event listeners */
          bindUi = function(){
            imgInput.addEventListener( "change", function(){
              if ( this.files.length ) {
                var reader = new FileReader();
                reader.onload = function( e ){
                  window.localStorage.setItem( "image-base64", e.target.result );
                  updateUi();
                };
                reader.readAsDataURL( this.files[ 0 ] );
              }
            }, false );
          };

    updateUi();
    bindUi();
    }());
    </script>
    </body>
    </html>