我想在src
img
属性的mjpeg网址中发送凭据HTTP标头。
由于不可能直接,我正在寻找一种方法来在我的反应应用程序中显示mjpeg流。
首先尝试:使用提取API
mjpeg(cameraId, cb) {
const abortController = new AbortController();
const signal = abortController.signal;
fetch(this.endpoint + "camera/get/mjpeg/" + cameraId + "/", {
method: "GET",
headers: this.getHeaders(),
mode: "cors",
redirect: "follow",
signal
}).then((response) => {
const reader = response.body.getReader();
let imageBuffer = [];
const stream = new ReadableStream({
start(controller) {
// The following function handles each data chunk
const push = () => {
// "done" is a Boolean and value a "Uint8Array"
return reader.read().then(({ done, value }) => {
let i = 0;
while (i < value.length) {
if (i < (value.length - 2)) {
// New image
if (value[i] === 255 && value[i+1] === 216) {
// console.log("jpeg found !");
imageBuffer = [];
}
// End image
if (value[i] === 255 && value[i+1] === 217) {
// console.log("jpeg end !" + i + " / " + value.length);
imageBuffer.push(value[i]);
imageBuffer.push(value[i + 1]);
const _arrayBufferToBase64 = (buffer) => {
var binary = '';
var bytes = new Uint8Array( buffer );
var len = bytes.byteLength;
for (var i = 0; i < len; i++) {
binary += String.fromCharCode( bytes[ i ] );
}
return window.btoa( binary );
};
cb(null, false, _arrayBufferToBase64(imageBuffer));
imageBuffer = [];
i++;
} else {
imageBuffer.push(value[i]);
}
} else {
imageBuffer.push(value[i]);
}
i++;
}
// Protect buffer
if (imageBuffer.length > 4000000) {
imageBuffer = [];
}
// Is there no more data to read?
if (done) {
// Tell the browser that we have finished sending data
cb(null, true);
return;
}
// Get the data and send it to the browser via the controller
if (abortController.signal.aborted) {
throw Error("Stream aborted");
} else {
try {
controller.enqueue(value);
} catch(e) {
}
}
}).then(push);
};
push();
}
});
const abort = () => {
stream.cancel();
abortController.abort();
};
cb(null, false, null, abort);
return new Response(stream, { headers: { "Content-Type": "image/jpeg" } });
}).catch((error) => {
cb(error, true);
});
}
使用此代码,我可以在容器中成功显示图像,可以停止流(不干净 - 抛出异常)。 按预期工作,但仅适用于Chrome ,而非Safari或Firefox。
第二次尝试:使用XMLHttpRequest
我想用XMLHttpRequest做同样的过程。所以我可以手动添加标题并在传输过程中解密流。
但我有这些问题:
Stream似乎仅适用于responseText
,而非response
。
我无法正确转换responseText
到Uint8Array
我想要一个带有流阅读器的fetch API解决方案,这在firefox / safari下根本不起作用。
有什么想法吗?