?
????????是這樣的需求,有一個(gè)web頁面,里面圖片的上傳和預(yù)覽來自于一個(gè)獨(dú)立的文件服務(wù)器,對(duì)http的請(qǐng)求需要進(jìn)行訪問權(quán)限的設(shè)置,就是在請(qǐng)求的header里加一個(gè)Authorization的字段。上傳好說我用的Axios直接添加一個(gè)header就行了,但是預(yù)覽就比較麻煩了,因?yàn)?code>img這個(gè)標(biāo)簽圖片下載展示是瀏覽器自己實(shí)現(xiàn)的,沒有辦法去修改。所以首先想到就是通過接口添加自定義header轉(zhuǎn)發(fā)請(qǐng)求或者其他通過接口的方案了,那怎么通過前端頁面去實(shí)現(xiàn)這個(gè)功能,首先聲明的是這里用了一些新的API,所以如果是一些比較老的瀏覽器那就沒法這么做了。
????????問題分析:img
標(biāo)簽的src屬性只能設(shè)置url,不能設(shè)置這次請(qǐng)求的header。既然這樣,能不能通過別的方式先把圖片下載下來然后再給img標(biāo)簽作展示,相當(dāng)于把src屬性的下載和展示分成了兩步,先調(diào)用接口獲取到了數(shù)據(jù),然后再把數(shù)據(jù)給展示出來,也就是src里的值不是一個(gè)url地址而是一個(gè)數(shù)據(jù)流。
????????可以這樣,首先通過Object.defineProperty定義一個(gè)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://threex.top/images/image_201909111450326.jpg">
</body>
</html>
????????這樣雖然可以實(shí)現(xiàn)功能,但是每次還需要執(zhí)行額外的腳本,不能在Dom加載完的時(shí)候自動(dòng)去下載展示,不夠優(yōu)雅。能不能自動(dòng)去下載展示呢
?????? 通過自定義元素加載
????????自定義元素不太了解的可以參考這里Using custom elements,這里還有個(gè)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://threex.top/images/image_201909111450326.jpg">
</body>
</html>
????????利用Node作請(qǐng)求轉(zhuǎn)發(fā)
????????這里我是在Electron客戶端用的,是通過進(jìn)程間通信的方式獲取到了用戶憑證信息,如果是部署在服務(wù)器上的話,應(yīng)該使用其他方式。文章來源:http://www.zghlxwxcb.cn/news/detail-442199.html
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!');
})
????????利用Nginx?
????????既然作請(qǐng)求轉(zhuǎn)發(fā),那Nginx自然也是可以的,但是Nginx里添加header都是固定,沒法去修改,想到了一個(gè)方式,先請(qǐng)求一個(gè)地址攜帶token,然后自定義一個(gè)變量,去設(shè)置這個(gè)值。這個(gè)方式有點(diǎn)惡心,一來是把token暴露了出來,二來是容易造成誤傷,一不小心就把token更新了,而且假如Nginx重啟了這時(shí)候token也沒了。只作為一個(gè)思路拓展了,是不能這么搞的,大概像下面這樣。文章來源地址http://www.zghlxwxcb.cn/news/detail-442199.html
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;
}
}
到了這里,關(guān)于如何給img標(biāo)簽里的請(qǐng)求添加自定義header的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!