2012-05-08 24 views
12

Tôi cần lưu trữ một số phía máy khách dữ liệu và dữ liệu này quá lớn để lưu trữ nó trong cookie. LocalStorage dường như là cách hoàn hảo để thực hiện điều này, nhưng trang web mà tôi sẽ sử dụng có một số phần hoạt động trên https và các phần khác chỉ với http và lưu trữ cục bộ không thể truy cập dữ liệu từ https mà bạn đã đặt bằng http điều này dường như không còn là một giải pháp khả thi nữa.Có cách nào khác để sử dụng tính năng lưu trữ địa phương html5 trên cả http và https không?

Bất kỳ ý tưởng nào nếu có giải pháp nào cho điều này? Bất kỳ lựa chọn thay thế nào khác?

+0

liên quan (1) [cùng localStorage cho http và https?] (Http://stackoverflow.com/questions/5144471/same-localstorage-for- http-and-https), (2) [Cơ sở dữ liệu HTML5 và localStorage có thể được chia sẻ trên các tên miền phụ không?] (http://stackoverflow.com/questions/4177803/can-html5-databases-and-localstorage-be-shared-across -subdomains). –

Trả lời

21

Lưu trữ tất cả dữ liệu trên một tên miền, ví dụ: https://my.domain.org/.

  • Trên giao thức https, chỉ cần sử dụng localStorage.setItem('key', 'value') để lưu dữ liệu.
  • On http giao thức, nhúng một khung https, và sử dụng postMessage để lưu các dữ liệu:

Demo: http://jsfiddle.net/gK7ce/4/ (với trang helper được đặt tại http://jsfiddle.net/gK7ce/3/).

// Script at https://my.domain.org/postMessage 
window.addEventListener('message', function(event) { 
    // Domain restriction (to not leak variables to any page..) 
    if (event.origin == 'http://my.domain.org' || 
     event.origin == 'https://my.domain.org') { 
     var data = JSON.parse(event.data); 
     if ('setItem' in data) { 
      localStorage.setItem(data.setItem, data.value); 
     } else if ('getItem' in data) { 
      var gotItem = localStorage.getItem(data.getItem); 
      // See below 
      event.source.postMessage(
       '#localStorage#' + data.identifier + 
       (gotItem === null ? 'null#' : '#' + gotItem), 
       event.origin 
      ); 
     } else if ('removeItem' in data) { 
      localStorage.removeItem(data.removeItem); 
     } 
    } 
}, false); 

Trên trang http (s), khung có thể được nhúng như sau (thay https://my.mydomain.com với URL thực tế. Lưu ý rằng bạn chỉ có thể có được một tham chiếu đến các khung hình, và sử dụng thuộc tính src) :

<iframe name="myPostMessage" src="https://my.domain.org/postMessage" style="display:none;"></iframe> 
// Example: Set the data 
function LSsetItem(key, value) { 
    var obj = { 
     setItem: key, 
     value: value 
    }; 
    frames['myPostMessage'].postMessage(JSON.stringify(obj), 'https://my.domain.com'); 
} 
LSsetItem('key', 'value'); 

Lưu ý rằng phương pháp này không đồng bộ, vì postMessage. Việc triển khai phương pháp getItem phải được thực hiện khác nhau:

var callbacks = {}; 
window.addEventListener('message', function(event) { 
    if (event.source === frames['myPostMessage']) { 
     var data = /^#localStorage#(\d+)(null)?#([\S\s]*)/.exec(event.data); 
     if (data) { 
      if (callbacks[data[1]]) { 
       // null and "null" are distinguished by our pattern 
       callbacks[data[1]](data[2] === 'null' ? null : data[3]); 
      } 
      delete callbacks[data[1]]; 
     } 
    } 
}, false); 
function LSgetItem(key, callback) { 
    var identifier = new Date().getTime(); 
    var obj = { 
     identifier: identifier, 
     getItem: key 
    }; 
    callbacks[identifier] = callback; 
    frames['myPostMessage'].postMessage(JSON.stringify(obj), 'https://my.domain.com'); 
} 
// Usage: 
LSgetItem('key', function(value) { 
    console.log('Value: ' + value); 
}); 

Lưu ý rằng mỗi cuộc gọi được lưu trữ trong băm. Mỗi tin nhắn cũng chứa một số nhận dạng, để cửa sổ nhận được tin nhắn gọi lại lời gọi tương ứng chính xác.

Để hoàn chỉnh, đây là phương pháp LSremoveItem:

function LSremoveItem(key) { 
    var obj = { 
     removeItem: key 
    }; 
    frames['myPostMessage'].postMessage(JSON.stringify(obj), 'https://my.domain.com'); 
} 
+0

Tôi đã thử điều này nhưng khi iframe https cố gắng postMessage quay lại cửa sổ http cha mẹ tôi gặp lỗi "Truy cập JavaScript không an toàn để truy cập khung bằng URL ... Tên miền, giao thức và cổng phải khớp." Bất kỳ ý tưởng? – daniels

+1

Mọi [SSCCE] (http://sscce.org/)? –

+0

Tôi đang sử dụng: https://github.com/mozilla/jschannel và mẫu này https://github.com/mozilla/jschannel/tree/master/example – daniels

Các vấn đề liên quan