How to display playable Video Url from Blob - javascript

I am trying to download videos from a webDav server to my server. After that the videos should be viewable as well as playable on my client. For downloading I use the webdav library from npm.
The download of the videos works on my server, as well as the transmission of the data to my client. My Problem is, I can't play those videos on the generated website.
app.post("/someroute/api", async (req, res) => {
let result = [];
try {
const { username, password, targetUrl, data } = req.body;
const dataFull = `somedata_${data}`;
const client = createClient(targetUrl, {
username: username,
password: password,
});
const filesToDownload = await client.getDirectoryContents(`/${dataFull}`);
const downloadPromises = filesToDownload.map(async (file) => {
const fileBuffer = await client.getFileContents(file.filename);
result.push({name: file.basename, buffer: fileBuffer});
});
await Promise.all(downloadPromises);
} catch (error) {
console.error(error);
res.status(500).json({ error: "Error retrieving directory contents" });
}
console.log(result);
res.send(result);});
The result looks like this :
{ name: 'butterfly slow motion [oAI-OqTmJj4].mp4',
buffer: <Buffer 00 00 00 18 66 74 79 70 6d 70 34 32 00 00 00 00 69 73 6f 6d 6d 70 34 32 00 00 40 d7 6d 6f 6f 76 00 00 00 6c 6d 76 68 64
00 00 00 00 d8 cd f6 85 d8 cd ... 4073099 more bytes> }
On the client side I have this function to request the videos and store them in a useState.
useEffect(() => {
if (selectedData) {
getDataVideos();
}
}, [selectedData]);
const getDataVideos = async () => {
try {
const response = await fetch("/someroute/api", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
username: username,
password: password,
targetUrl: targetUrl,
data: selectedData,
}),
});
const content = await response.json();
console.log(content);
setSelectedDataVideos(content);
} catch (error) {
console.error(error);
}
};
the console.log() of the selectedDataVideos is :
Array (1) 0 Object
buffer: {type: "Buffer", data: Array}
name: "butterfly slow motion [oAI-OqTmJj4].mp4"
Later I transform the videos into a blob using this method and safe the result into a usestate
const [tempUrls, settempUrls] = useState([]);
, here a snapshot of it :
const blob = new Blob([video.buffer.data], { type: "video/mp4" });
console.log("Videoslide 2 blob")
console.log(blob)
const url = URL.createObjectURL(blob);
return {name:video.name,url:url};
The blobs are saved in a usestate const [tempUrls, settempUrls] = useState([]);
The blob itself looks like this :
[Log] Blob {size: 14484621, type: "video/mp4", slice: function,
stream: function, text: function, …}
An index the tempUrls looks finished like this :
[Log] {name: "butterfly slow motion [oAI-OqTmJj4].mp4", url:
"blob:http:// localhost:8081/ed893b3d-298f-40c4-b4c0-1c3ac688aa43"}
The space in http:// localhost is for removing the hyperlink here.
For display the video and to play it I have this :
{tempUrls.map(video =>
<div key={video.name} style={{ flex: 2, padding: "15px 20px" }}>
<video
src={video.url}
controls
type="video/mp4"
>
</video>
Only the control placeholder is displayed but I can't play the video. Also, when I open the web page in Firefox this is displayed. "No video with supported format and MIME type found". But I am not clear where exactly I made the mistake when converting. Actually I converted the array buffer to a blob of type mp4/video and then to a URL. Then saved it as object {filename, url} in a usestate and from this usestate the videos should be played/displayed.
Does anyone here possibly see the error, I've been sitting on it a bit longer without finding it. The video itself is not corrupted, ive stored it in a docker next cloud server and can play it there without problems.

Solved it by using
import { Buffer } from "buffer";
from npm to convert the arraybuffer.
let buffer = Buffer.from(item.buffer.data);
const blob = new Blob([buffer], { type: "video/mp4" });
const url = URL.createObjectURL(blob);
result.push({ name: item.name, url: url });

Related

S3 GetObject Returning Weird Encoding for HTML file

I am attempting to read an HTML file into a Lambda Edge function and then return it in the response body, but for some reason, I cannot get it to return the contents of the HTML file correctly.
Here is my code (simplified):
const AWS = require('aws-sdk');
const S3 = new AWS.S3({
signatureVersion: 'v4'
});
const { Body } = await S3.getObject({ Bucket: 'my-bucket', Key: 'index.html' }).promise();
console.log(Body.toString());
Instead of seeing <html... in the console log, I am seeing the dreaded question mark characters which implies (I think), bad encoding:
��Y�r#��x�`�,b�J�ٲ��NR�yIٮ�!!���"���n���޴��Is�>}�n4pF�_���de�nq�~�]� f�����v��۔*�㺮Ý� Hdž�<�! �c�5�1B��,#|Ŵ;ֶ�U����z� �Qi��j�0��V ���H���...etc
I have literally tried everything including, but not limited to:
Body.toString('utf-8');
Body.toString('ascii');
Body.toString('base64');
decoder.write(Body.toString('base64'));
and a lot more...
I think I must be missing something really obvious here as I cannot find anyone else facing the same issue. I thought it might be to do with the encryption but my other Lambda Edge function reads an image file without issues so I assume it has to be something to do with encoding that I haven't thought of.
UPDATE
I believe the issue may be related to the fact that the file is gzipped.
Here is a print of the response from S3:
{
AcceptRanges: 'bytes',
LastModified: 2023-02-17T19:44:41.000Z,
ContentLength: 1598,
ETag: 'some-key',
CacheControl: 'max-age=31536000',
ContentEncoding: 'gzip',
ContentType: 'text/html; charset=UTF-8',
ServerSideEncryption: 'AES256',
Metadata: { etag: 'some-key' },
Body: <Buffer 1f 8b 08 00 00 00 00 00 00 03 cd 59 db 72 23 b7 11 fd 15 78 f2 60 bb 2c 62 ee b7 8d c8 4a b2 d9 b2 b7 ca 4e 52 bb 79 49 d9 ae 14 06 e8 21 21 cd 0c a6 ... 1548 more bytes>
}
The issue was caused by the fact that the index.html file was gzipped. The solution to handling this is as follows:
const AWS = require('aws-sdk');
const zlib = require('zlib');
const S3 = new AWS.S3({
signatureVersion: 'v4'
});
const { Body } = await S3.getObject({ Bucket: 'my-bucket', Key: 'index.html' }).promise();
const body = zlib.unzipSync(Body).toString();
console.log(body);
However, given that this code is being deployed within a Lambda Edge function, speed is essential! With that in mind, it would/should be faster to actually utilise https.get as this will automatically unzip the contents of the file prior to returning the Buffer stream.

NodeJS Server - Unable to read POST request body

I'm trying to create a simple account system on a Nodejs HTTP Server.
My Server-side code:
var server=http.createServer(function(req,res){
if(req.url.startsWith("/api/")){
console.log(" - // - API CALL - // -")
switch (req.url.substr(4)) {
case '/createAccount':
if(req.method=="POST"){
const requestBody = [];
req.on('data', (chunks)=>{
requestBody.push(chunks);
console.log(chunks)
});
req.on('end', ()=>{
console.log(requestBody)
const parsedData = JSON.stringify(Buffer.concat(requestBody));
console.log(parsedData)
res.writeHead(200,{"Content-Type":"application/json","Access-Control-Allow-Origin": "*"});
res.end(JSON.stringify({'error':false}));
});
}else{
res.writeHead(405,{"Content-Type":"application/json","Access-Control-Allow-Origin": "*"});
res.end(JSON.stringify({'error':true,'statuscode':'405','errortext':'You need to send a POST request to /createAccount.'}));
}
break;
default:
res.writeHead(404,{"Content-Type":"application/json","Access-Control-Allow-Origin": "*"});
res.end(JSON.stringify({'error':true,'statuscode':'404','errortext':'This is not a valid API address.'}));
}
}else{
console.log(" - // - NORMAL WEB PAGE - // -")
res.writeHead(200,{"Content-Type":"text/html","Access-Control-Allow-Origin": "*"});
let accountstate="not logged in"
page="<html><body>This is my homepage!<br>You are "+accountstate+".</body></html>";
res.end(page);
}
});
server.listen(7000);
console.log(`Listening at http://localhost:7000`);
The request I'm sending:
fetch("http://localhost:7000/api/createAccount",{
method:"POST",
body:{
AccountName:"test",
Password:"THISSHOULDBEENCRYPTED"
}
}).then(r=>r.json()).then(r=>console.log(r))
The console output after sending the request:
- // - API CALL - // -
<Buffer 5b 6f 62 6a 65 63 74 20 4f 62 6a 65 63 74 5d>
[ <Buffer 5b 6f 62 6a 65 63 74 20 4f 62 6a 65 63 74 5d> ]
{"type":"Buffer","data":[91,111,98,106,101,99,116,32,79,98,106,101,99,116,93]}
Does anyone have an idea why this is the output and how I can read the plain request body? (Expected output: {AccountName:"test",Password:"THISSHOULDBEENCRYPTED"})
I have looked for answers on many sites, but all solutions failed in the same error.
Thanks in advance!
Here is my fixed code:
var server=http.createServer(function(req,res){
if(req.url.startsWith("/api/")){
console.log(" - // - API CALL - // -")
switch (req.url.substr(4)) {
case '/createAccount':
if(req.method=="POST"){
req.setEncoding('utf8');
const rb = [];
req.on('data', (chunks)=>{
rb.push(chunks);
});
req.on('end', ()=>{
const body=JSON.parse(rb.join(""));
console.log(body)
res.writeHead(200,{"Content-Type":"application/json","Access-Control-Allow-Origin": "*"});
res.end(JSON.stringify({'error':false,'recieved':body}));
});
}else{...}
break;
default:
...
}
}else{...}
});
server.listen(7000);
console.log(`Listening at http://localhost:7000`);
And the fixed request:
fetch("http://localhost:7000/api/createAccount",{
method:"POST",
Headers:{'Content-Type': 'application/json'},
body:JSON.stringify({
AccountName:'test',
Password:'THISSHOULDBEENCRYPTED'
})
}).then(r=>r.json()).then(r=>console.log(r))
Basically, setting the Encoding to UTF8 and sending the body as a String will fix this issue.

azure storage upload image file and get its url to display with img tag

I want use azure file storage to store image file
and i can upload image file with below code
...
const uploadBlobResponse = await blockBlobClient.uploadFile('./test.png');
console.log('Blob was uploaded successfully. requestId: ', uploadBlobResponse);
And output is
Blob was uploaded successfully. requestId: {
etag: '"0x8D8FCCEC050FDB7"',
lastModified: 2021-04-11T09:46:59.000Z,
contentMD5: <Buffer a6 c1 b2 ef 44 0d 59 d2 33 43 ea c3 03 06 3f e3>,
clientRequestId: 'c261dccb-1b2f-4802-9768-c98bb59cc8b4',
requestId: '686eda5f-301e-00c0-49b7-2ead12000000',
version: '2020-06-12',
versionId: undefined,
date: 2021-04-11T09:46:58.000Z,
isServerEncrypted: true,
encryptionKeySha256: undefined,
encryptionScope: undefined,
errorCode: undefined,
'content-length': '0',
server: 'Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0',
'x-ms-content-crc64': 'F99Vk4U+TkE=',
body: undefined
}
So, I cannot get the image's public URL.
How I can do this?
BlockBlobClient has a url property that will give you the URL of the blob. Something like:
const uploadBlobResponse = await blockBlobClient.uploadFile('./test.png');
console.log('Blob was uploaded successfully. requestId: ', uploadBlobResponse);
console.log('Blob URL: ', blockBlobClient.url);
However, even though the URL is the public URL of the blob it may still result in 404 (Not Found) error if the blob is inside a blob container with Private ACL. You will need to use a Shared Access Signature URL of the blob with at least Read permission to view the blob by its URL.

Nodejs: make a GET request with users parameters

I'm new in nodejs. I'm making a express server. I recive some parameter by url, and I wnat to make a request to another server with the parameters in the recived url.
var express = require("express"),
app = express(),
bodyParser = require("body-parser"),
methodOverride = require("method-override");
request = require('request');
Client = require('node-rest-client').Client;
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(methodOverride());
var router = express.Router();
app.use(router);
router.get('/get_metric_names_by_pattern', function(req, res) {
console.log('get_metric_names_by_pattern '+req.url);
console.log(req.query.pattern);
//console.log(req.parameters);
res.header('Access-Control-Allow-Origin', '*');
var client = new Client();
var salida;
console.log(req.params.name);
//Creamos la variable para los parametros
var args = {
parameters: {pattern: "OEE"}
//headers: { "test-header": "client-api" }
};
console.log(args);
console.log(args.parameters.pattern);
client.get('http:// localhost:8000/get_metric_names_by_pattern/?pattern=:pattern', req.query.pattern,
//http:// localhost:8000/get_metric_names_by_pattern/?pattern=OEE
function (data, response) {
//console.log(args.parameters.pattern);
console.log(data);
//var pattern = req.query.pattern;
//data = data.toString('utf8'); //Transformamos los datos a string para que los reconozca el navegador
//console.log(data);
salida = JSON.parse(data);
//console.log("Datos:", salida.date);
res.send(salida); //Lo enviamos al navegador
//console.log(salida);
});
});
I do recive the paramteter from the client (in this case 'OEE') but I find no way to insert that string into client.get('http:// localhost:8000/get_metric_names_by_pattern/?pattern=:pattern', req.query.pattern, .
The request should look like the commented line under that one ( //http://localhost:8000/get_metric_names_by_pattern/?pattern=OEE) and from that request I'm recibing a json, just like this :
["PanelPC0_OEE", "empacadora1.OEE", "empacadora1.OEEE", "empacadora1.OEE_Avaible", "empacadora1.OEE_Performance", "empacadora1.OEE_quality"]
The console.log look like this:
node servicio.js
Servidor corriendo en: http:// localhost:3000
get_metric_names_by_pattern /get_metric_names_by_pattern/?pattern=OEE
OEE
undefined
{ parameters: { pattern: 'OEE' } }
OEE
Buffer 5b 5d
and it should look like :
node servicio.js
Servidor corriendo en: http:// localhost:3000
get_metric_names_by_pattern /get_metric_names_by_pattern/?pattern=OEE
OEE
undefined
{ parameters: { pattern: 'OEE' } }
OEE
Buffer 5b 22 50 61 6e 65 6c 50 43 30 5f 4f 45 45 22 2c 20 22 74 65 61 6d 66 6f
6f 64 73 2e 62 6f 67 6f 74 61 2e 6d 61 72 67 61 72 69 6e 61 73 2e 65 6d 70 61 ..
.
Please, I need to know how to insert that parameter into the new url. Sorry if this post is to long or obvius. Thanks in advance
According to the documentation, to insert a parameter or argument you should use:
${param}
like this example:
var args = {
path: { "id": 120, "arg1": "hello", "arg2": "world" },
parameters: { arg1: "hello", arg2: "world" },
headers: { "test-header": "client-api" }
};
client.get("http://remote.site/rest/json/${id}/method?arg1=${arg1}&arg2=${arg2}", args,
function (data, response) {
console.log(data);
console.log(response);
});
so in your case you should try to use:
var args = {
parameters: { pattern: req.query.pattern },
};
client.get('http:// localhost:8000/get_metric_names_by_pattern/?pattern=${pattern}', args,
function(data, response){
});
although it is not pretty... the comment of #mrwillihog gave me this idea, wich actually works!
urln = 'http://localhost:8000/get_metric_names_by_pattern/?pattern='+req.query.pattern;
console.log(urln);
client.get(urln, function (data, response) { });

Problems with converting buffer to JS object

I'm using the mosca library for a MQTT broker and this for MQTT client.
The client code looks like this:
client.on('connect', function () {
client.subscribe('presence')
var json = {
someVar: 888,
someNum: 234
}
client.publish('presence', JSON.stringify(json));
});
client.on('message', function (topic, message) {
var json = JSON.parse(message.toString())
console.log(json.someVar);
client.end();
});
The broker, where each published message is handled is here:
server.on('published', function(packet, client) {
console.log('Package received:')
console.log('Published', packet);
var stringBuf = packet.payload.toString('utf-8')
console.log('buffer to string:', stringBuf)
var stringify = JSON.stringify(packet.payload)
console.log('stringify:',stringify);
var json = JSON.parse(stringily);
}
The output for buffer to string: looks like this:
{"someVar":888,"someNum":234}
Which should be valid json. But whenever I try to access the json-object (after using JSON.parse()) it just returns undefined for the variables.
I've also tried to do
var buf = json.data;
console.log('buffer data:', but);
But that just returns a buffer array, which can't seem to convert either.
In the client function I can easily parse the string to a JS object, so I'm a bit lost as to what is happening.
Any suggestions? Thanks.
Like stdob-- said, you're trying to parse all incoming messages, example of output for your example:
Package received:
Published mqttjs_05cac308
Package received:
Published {"clientId":"mqttjs_05cac308","topic":"presence"}
Package received:
Published <Buffer 7b 22 73 6f 6d 65 56 61 72 22 3a 38 38 38 2c 22 73 6f 6d 65 4e 75 6d 22 3a 32 33 34 7d>
Package received:
Published {"clientId":"mqttjs_05cac308","topic":"presence"}
Package received:
Published mqttjs_05cac308
You can check for the topic to handle the presence message you need:
server.on('published', function (packet, client) {
if (packet.topic == 'presence') {
var stringBuf = packet.payload.toString('utf-8');
var obj = JSON.parse(stringBuf);
console.log(obj);
}
});
/* output: { someVar: 888, someNum: 234 } */
You receive an error because tries to parse all incoming messages, including service messages that do not contain the pure JSON data. Try this:
server.on('published', function(packet, client) {
console.log('Package received:')
console.log('Published', packet);
var stringBuf = packet.payload.toString('utf-8')
try {
var json = JSON.parse(stringBuf);
console.log( json );
} catch (e) {
console.log( stringBuf );
}
}

Categories