如何給img標簽里的請求添加自定義header?


是這樣的需求,有一個web頁面,里面圖片的上傳和預覽來自於一個獨立的文件服務器,對http的請求需要進行訪問權限的設置,就是在請求的header里加一個Authorization的字段。上傳好說我用的Axios直接添加一個header就行了,但是預覽就比較麻煩了,因為img這個標簽圖片下載展示是瀏覽器自己實現的,沒有辦法去修改。所以首先想到就是通過接口添加自定義header轉發請求或者其他通過接口的方案了,那怎么通過前端頁面去實現這個功能,首先聲明的是這里用了一些新的API,所以如果是一些比較老的瀏覽器那就沒法這么做了。

問題分析:img標簽的src屬性只能設置url,不能設置這次請求的header。既然這樣,能不能通過別的方式先把圖片下載下來然后再給img標簽作展示,相當於把src屬性的下載和展示分成了兩步,先調用接口獲取到了數據,然后再把數據給展示出來,也就是src里的值不是一個url地址而是一個數據流。

可以這樣,首先通過Object.defineProperty定義一個authSrc屬性用來替換src屬性的值,然后在window.onload里等dom加載完以后去再下載圖片。

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Proxy Image</title> <script> Object.defineProperty(Image.prototype, 'authsrc', { writable : true, enumerable : true, configurable : true }) window.onload = () => { let img = document.getElementById('img'); let url = img.getAttribute('authsrc'); let request = new XMLHttpRequest(); request.responseType = 'blob'; request.open('get', url, true); request.setRequestHeader('Authorization', '憑證信息'); request.onreadystatechange = e => { if (request.readyState == XMLHttpRequest.DONE && request.status == 200) { img.src = URL.createObjectURL(request.response); img.onload = () => { URL.revokeObjectURL(img.src); } } }; request.send(null); } </script> </head> <body> <img width="100" height="100" id="img" authsrc="http://39.106.118.122/images/image_201909111450326.jpg"> </body> </html>

這樣雖然可以實現功能,但是每次還需要執行額外的腳本,不能在Dom加載完的時候自動去下載展示,不夠優雅。能不能自動去下載展示呢

 

通過自定義元素加載

自定義元素不太了解的可以參考這里Using custom elements,這里還有個w3c的草案autonomous-custom-element。

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Proxy Image</title> <script> let requestImage = function (url, element) { let request = new XMLHttpRequest(); request.responseType = 'blob'; request.open('get', url, true); request.setRequestHeader('Authorization', '憑證信息'); request.onreadystatechange = e => { if (request.readyState == XMLHttpRequest.DONE && request.status == 200) { element.src = URL.createObjectURL(request.response); element.onload = () => { URL.revokeObjectURL(element.src); } } }; request.send(null); } class AuthImg extends HTMLImageElement { constructor() { super(); this._lastUrl = ''; } static get observedAttributes() { return ['authSrc']; } connectedCallback() { let url = this.getAttribute('authSrc'); if (url !== this._lastUrl) { this._lastUrl = url; requestImage(url, this); } console.log('connectedCallback() is called.'); } } window.customElements.define('auth-img', AuthImg, {extends: 'img'}); </script> </head> <body> <img width="100" height="100" is="auth-img" authSrc="http://39.106.118.122/images/image_201909111450326.jpg"> </body> </html>

 

利用Node作請求轉發

這里我是在Electron客戶端用的,是通過進程間通信的方式獲取到了用戶憑證信息,如果是部署在服務器上的話,應該使用其他方式。

let app = http.createServer((request, response) => {
    let config = {
        host: 'xxx.com', method: 'GET', path: request.url, headers: { Authorization: '用戶憑證' } }; let proxyRequest = http.request(config, proxyResponse => { proxyResponse.on('data', data => { response.write(data, 'image/jpg'); }); proxyResponse.on('end', () => { response.end(); }); response.writeHead(proxyResponse.statusCode, proxyResponse.headers); }) request.on('data', data => { proxyRequest.write(data, 'image/jpg'); }) request.on('end', () => { proxyRequest.end(); }) }); app.listen(port, () => { console.log('has start proxy server!'); })

電腦刺綉綉花廠 http://www.szhdn.com 廣州品牌設計公司https://www.houdianzi.com

利用Nginx

既然作請求轉發,那Nginx自然也是可以的,但是Nginx里添加header都是固定,沒法去修改,想到了一個方式,先請求一個地址攜帶token,然后自定義一個變量,去設置這個值。這個方式有點惡心,一來是把token暴露了出來,二來是容易造成誤傷,一不小心就把token更新了,而且假如Nginx重啟了這時候token也沒了。只作為一個思路拓展了,是不能這么搞的,大概像下面這樣。

 
server {

    ...
    
    set $AUTH_TOKEN ""; location /token/([0-9a-z])$ { set $AUTH_TOKEN $1; return 200; } location /image { proxy_pass http://xxx.com; proxy_set_header Authorization $AUTH_TOKEN; } }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM