2011-02-07 35 views
12

Tôi muốn xem liệu tab hiện tại có phải là tệp PDF từ trang nền hay không.Tôi làm cách nào để phát hiện loại mime của tab hiện tại trong tiện ích Google Chrome?

Tôi có thể kiểm tra url cho .pdf ở cuối nhưng có một số tệp PDF không có.

+0

Bạn đã bao giờ phát triển tiện ích mở rộng có chức năng này chưa? Tôi rất thích có một phần mở rộng như vậy, nhưng không muốn tìm hiểu làm thế nào để mã hóa một cho một vài sử dụng cá nhân. – msbg

Trả lời

4

Bạn không thể sử dụng tính năng này bằng cách sử dụng API API hiện tại. Những gì bạn có thể làm là tải lại trang này thông qua XHR và kiểm tra tiêu đề loại nội dung trả về. Một cái gì đó như thế này:

nền html:

chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) { 
    if(changeInfo.status == "loading") { 
     if(checkIfUrlHasPdfExtension(tab.url)) { 
      //.pdf 
      pdfDetected(tab); 
     } else { 
      var xhr = new XMLHttpRequest(); 
      xhr.open("GET", tab.url, true); 
      xhr.onreadystatechange = function() { 
       if (xhr.readyState == 4) { 
       var contentType = xhr.getResponseHeader("Content-Type"); 
       if(checkIfContentTypeIsPdf(contentType)) { 
        pdfDetected(tab); 
       } 
       } 
      } 
      xhr.send(); 
     } 
    } 
}); 

manifest.json:

"permissions": [ 
    "tabs", "http://*/*", "https://*/*" 
] 

Đối với các file PDF trở kiểu nội dung nên application/pdf. Một điều cần lưu ý là tiêu đề kiểu nội dung cũng có thể chứa mã hóa: text/html; charset=UTF-8.

+1

Cảm ơn tôi tin rằng điều đó sẽ hiệu quả. Nhưng tôi sợ tôi sẽ không sử dụng nó vì mỗi trang sẽ được tải hai lần. – Orny

+0

@Orny Tôi đồng ý, tôi sẽ chỉ kiểm tra phần mở rộng pdf, đủ cho 99% trường hợp – serg

+0

Tôi đã tìm kiếm một cái gì đó như thế này, và bởi vì tôi sẽ sử dụng nó chỉ khi mở cửa sổ mở rộng, tôi nghĩ (hy vọng) yêu cầu sẽ sử dụng trang được lưu trong bộ nhớ cache trong hầu hết các trường hợp. – Omiod

10

Việc đưa ra yêu cầu mới chỉ để loại MIME hơi nặng và không đáng tin cậy. Ví dụ: nếu trang hiện được hiển thị là kết quả của việc gửi biểu mẫu POST, thì việc yêu cầu GET thường sẽ không dẫn đến cùng một trang.

Nếu bạn đang phát triển tiện ích mở rộng thường xuyên cần quyền truy cập vào thông tin này, hãy sử dụng API chrome.webRequest để theo dõi phản hồi. Việc gia hạn bản demo sau đây cho thấy các kiểu nội dung khi click vào nút trình duyệt:

// background.js 
var tabToMimeType = {}; 
chrome.webRequest.onHeadersReceived.addListener(function(details) { 
    if (details.tabId !== -1) { 
     var header = getHeaderFromHeaders(details.responseHeaders, 'content-type'); 
     // If the header is set, use its value. Otherwise, use undefined. 
     tabToMimeType[details.tabId] = header && header.value.split(';', 1)[0]; 
    } 
}, { 
    urls: ['*://*/*'], 
    types: ['main_frame'] 
}, ['responseHeaders']); 

chrome.browserAction.onClicked.addListener(function(tab) { 
    alert('Tab with URL ' + tab.url + ' has MIME-type ' + tabToMimeType[tab.id]); 
}); 

function getHeaderFromHeaders(headers, headerName) { 
    for (var i = 0; i < headers.length; ++i) { 
     var header = headers[i]; 
     if (header.name.toLowerCase() === headerName) { 
      return header; 
     } 
    } 
} 

Ghi chú:

  • Phần mở rộng này chỉ cho thấy kết quả cho các tab được nạp sau phần mở rộng được tải.
  • Điều này chỉ hoạt động trên các trang http/https. ftp :, file :, filesystem :, blob :, data: không được hỗ trợ.
  • Khi không có loại MIME nào được chỉ định bởi máy chủ hoặc khi loại MIME là text/plain, Chrome rơi trở lại MIME sniffing trừ khi đặt X-Content-Type-Options: nosniff. Trong trường hợp đầu tiên, kiểu MIME được phát hiện có thể là bất cứ thứ gì. Trong trường hợp thứ hai, kiểu MIME mặc định là text/plain.

Để hoàn chỉnh, đây là một tập tin manifest.json có thể được sử dụng để kiểm tra mã theo thời gian:

{ 
    "name": "Click button to see MIME", 
    "version": "1", 
    "manifest_version": 2, 
    "background": { 
     "scripts": ["background.js"], 
     "persistent": true 
    }, 
    "browser_action": { 
     "default_title": "Show MIME" 
    }, 
    "permissions": [ 
     "webRequest", 
     "activeTab", 
     "*://*/*" 
    ] 
} 
+0

Câu trả lời của bạn rất chi tiết và hữu ích. Cảm ơn! –

+2

Thực sự hữu ích. Đây là cách tốt hơn so với câu trả lời được chấp nhận - không có phần mở rộng nên được yêu cầu lại tiêu đề trong thực tế. –

1

Một cách hơi hackish (Tôi không có ý tưởng nếu nó hoạt động luôn hay chỉ thỉnh thoảng) là xem nội dung trang. Ở đó bạn sẽ tìm thấy một phần tử cho trình xem PDF của chrome. Nó trông dọc theo các dòng này:

<embed width="100%" height="100%" name="plugin" src="https://example.com/document.pdf" type="application/pdf"> 

Bạn có thể kiểm tra thuộc tính "loại" đó để xem bạn đang xử lý những gì.

+1

Điều này thực sự đã lừa cho tôi, cảm ơn rất nhiều! Nó thực sự hơi hack nhưng nó có vẻ là cách duy nhất hoạt động cho URL "file: //" (miễn là manifest.json tuyên bố rằng các tập lệnh được tiêm phải đi vào URL khớp với bộ chọn "file: // *") . Đây là mã tôi đã sử dụng trong tập lệnh được chèn: 'if (document.body.childElementCount === 1) { \t var embed = document.body.firstElementChild; \t nếu (embed.tagName === "EMBED" && embed.getAttribute ("type") === "application/pdf") {/ * làm điều gì đó * /}} ' – robamler

0

Tôi phải làm điều gì đó tương tự trong một trong các tiện ích mở rộng của mình và đã làm điều gì đó rất giống với the answer do @serg đưa ra nhưng thay vào đó, sử dụng yêu cầu HEAD.Về lý thuyết, yêu cầu HEAD phải giống hệt với yêu cầu GET nhưng không gửi nội dung phản hồi, trong trường hợp hình ảnh hoặc tệp có thể khá nhiều dữ liệu và thời gian chờ đợi.

Tôi cũng chia và thay đổi tiêu đề để thả bất kỳ bộ ký tự nào có thể được thêm vào loại nội dung.

getContentType: function(tab, callback){ 
    var xhr = new XMLHttpRequest(); 
    xhr.open("HEAD", tab.url, false); 
    xhr.onload = function(e) { 
     if (xhr.readyState === 4) { 
      if(xhr.status === 200) { 
       callback(xhr.getResponseHeader("Content-Type").split(";").shift()); 
      } 
      else{ 
       callback('Unknown'); 
       console.error(xhr.statusText); 
       return; 
      } 
     } 
    }; 

    xhr.onerror = function (e) { 
     console.error(xhr.statusText); 
     return; 
    }; 

    xhr.send(); 
} 
Các vấn đề liên quan