Stream webcam/audio and save it as a file on server - Apache - javascript

I am curious about implementing one feature into my small project.
Basically, what I want is when I go to one specific page, I want to start recording video and audio with my webcam, and save that session in my Apache server. Now, the thing is that I want to stream that as a data, and not record it and then send that file to a server. The reason for that is because when I am done with that page, I will be transferred to a different page and I will not have time to do upload the whole video.
I have found this on one git page,
<?php
foreach(array('video', 'audio') as $type) {
if (isset($_FILES["${type}-blob"])) {
echo 'uploads/';
$fileName = $_POST["${type}-filename"];
$uploadDirectory = 'uploads/'.$fileName;
if (!move_uploaded_file($_FILES["${type}-blob"]["tmp_name"], $uploadDirectory)) {
echo(" problem moving uploaded file");
}
echo($fileName);
}
}
?>
And Javascript
var fileType = 'video'; // or "audio"
var fileName = 'ABCDEF.webm'; // or "wav"
var formData = new FormData();
formData.append(fileType + '-filename', fileName);
formData.append(fileType + '-blob', blob);
xhr('save.php', formData, function (fName) {
window.open(location.href + fName);
});
function xhr(url, data, callback) {
var request = new XMLHttpRequest();
request.onreadystatechange = function () {
if (request.readyState == 4 && request.status == 200) {
callback(location.href + request.responseText);
}
};
request.open('POST', url);
request.send(data);
}
but I am not sure if that is the streaming solution (as I mentioned), and not record and then upload.
I am using PHP with some Javascript and have Apache as a server.

Related

PHP to download zip file works when called directly but not from web application

I have a PHP code which produces a zip file and make it downloadable from browser. The download part looks like:
download.php
// force client download
if (headers_sent()) {
echo 'HTTP header already sent';
} else {
if (!is_file($zipFile)) {
header($_SERVER['SERVER_PROTOCOL'].' 404 Not Found');
echo $zipFile . ' not found';
} else if (!is_readable($zipFile)) {
header($_SERVER['SERVER_PROTOCOL'].' 403 Forbidden');
echo $zipFile . ' not readable';
} else {
ob_start();
// http headers for zip downloads
header('Content-Description: File Transfer');
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename="' . $zipName . '"');
header('Content-Transfer-Encoding: binary');
header('Connection: Keep-Alive');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
set_time_limit(0);
ob_flush();
ob_clean();
readfile($zipFile);
}
}
When called from the browser directly like localhost/download.php it works and makes me download the zipped file properly.
However, I need to call it from my JS web application.
The way I am invoking it is via a POST AJAX request that look like this:
var xhr;
if (window.XMLHttpRequest) xhr = new XMLHttpRequest(); // all browsers
else xhr = new ActiveXObject("Microsoft.XMLHTTP"); // for IE
var php_url = '/localhost/download.php' // ?wfs_url=' + url + 'format=' + format_list[0];
// (https://stackoverflow.com/a/53982364/1979665)
var formData = new FormData();
formData.append('wfs_url', url);
formData.append('format', format_list[0]);
xhr.open('POST', php_url);
xhr.onreadystatechange = function () {
if (xhr.readyState===4 && xhr.status===200) {
alert('Server reply: ' + xhr.responseText);
}
}
xhr.send(formData);
return false;
The code is triggered when I click on a button.
Apparently it's doing "something". The PHP intermediate outputs (some folders) are correctly created, but the download does not begin.
The alert('Server reply: ' + xhr.responseText); part shows a strange message with some messy symbols, which I guess derives from the files created and read as text somehow.
Here is a screenshot of the message:
The PHP script is sending the actual binary source of the zip file, while the AJAX request is trying to display it as text, that's the garbage you get.
If you really want to keep the AJAX (it would be more simple to just make a <form> that is sent to download.php), you could do one two things:
Just print the URL to $zipFile in PHP, and then when you get the response redirect to it with window.location.href=xhr.responseText;.
Save the response as a zip file. See How to save binary data of zip file in Javascript?
After following option 2 in #Gabriel accepted answer I was able to make my code working. Here is the modified version of the JS (I didn't make any change in the PHP code):
var php_url = '/localhost/download.php' // ?wfs_url=' + url + 'format=' + format_list[0];
// (https://stackoverflow.com/a/53982364/1979665)
var formData = new FormData();
formData.append('wfs_url', url);
formData.append('format', format_list[0]);
xhr.open('POST', php_url);
xhr.onreadystatechange = function () {
if (xhr.readyState===4 && xhr.status===200) {
var blob = new Blob([xhr.response], { // SOLUTION
type: "application/zip", // SOLUTION
}); // SOLUTION
var filename = "test.zip"; // SOLUTION
if (navigator.msSaveOrOpenBlob) { // SOLUTION
navigator.msSaveOrOpenBlob(blob, filename); // SOLUTION
} else { // SOLUTION
var a = document.createElement("a"); // SOLUTION
document.body.appendChild(a); // SOLUTION
a.style = "display:none"; // SOLUTION
var url = window.URL.createObjectURL(blob); // SOLUTION
a.href = url; // SOLUTION
a.download = filename; // SOLUTION
a.click(); // SOLUTION
window.URL.revokeObjectURL(url); // SOLUTION
a.remove(); // SOLUTION
} // SOLUTION
}
}
xhr.responseType = "arraybuffer"; // SOLUTION
xhr.send(formData);

Ajax taking too long to come back

I am recording 2-4 seconds of audio on my website and using Ajax I am posting it to the server. Some time this Ajax take 4-5 seconds, on the other hand some time it takes up to 2 minutes for uploading the same file. The file size is around 360kB. I want the Ajax to drop the file on the server and come back instantly and let the server keep processing it and meanwhile the user can start recording the next file.
I am using webRTC to record audios and working on Yii 1.x
//create FormData
var formData = new FormData();
formData.append(fileType + '-filename', fileName);
formData.append(fileType + '-blob', blob);
callback('Uploading ' + formData + ' recording to server.');
//ajax call
makeXMLHttpRequest('captureFile', formData, function(progress) {
if (progress !== 'upload-ended') {
callback(progress);
return ;
}
var initialURL = '<path to upload a file>';
callback('ended', initialURL + fileName);
});
function makeXMLHttpRequest(url, data, callback) {
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (request.readyState == 4 && request.status == 200) {
callback('upload-ended');
}
};
request.open('POST', url);
request.send(data);
};
on success next ajax perform its operation for initiating recording of the next file.
How can I make sure that this ajax only drop the file to the server and return back and server process the file and not stall ajax to finish file processing.

Image src not updating after setRequestHeader call

I have two AJAX functions: one for an image file upload, one for a form info upload.
File Upload
function uploadFile(insertNodeID, inputFileID){
var img = document.getElementById(inputFileID).files[0];
var form_data = new FormData();
form_data.append('file[]', img, img.name);
var objXML = new XMLHttpRequest();
objXML.onprogress = updateProgress;
objXML.onload = function() {
if(objXML.readyState==4 && objXML.status==200) {
if(objXML.responseText !== 'no'){
document.getElementById(insertNodeID).src = objXML.responseText;
}
else{
errorInOut('There was a problem uploading the file.');
}
}
};
objXML.open('POST', baseURL+'ajax/admin_fileupload/', true);
objXML.send(form_data);
Form Info Upload
function uploadFormInfo(strURL, strData, type) {
strURL = baseURL+'ajax/'+strURL+'/';
var objXML = new XMLHttpRequest();
objXML.onreadystatechange = function() {
if (objXML.readyState == 4 && objXML.status == 200) {
returnXML(objXML.responseText, type);
}
};
objXML.open("POST", strURL, true);
objXML.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
objXML.send(strData);
They both work perfect independently.
The issue I'm running into is when I call the uploadFormInfo(), then call uploadFile(), the document.getElementById(insertNodeID).src does not render the uploaded image. It still uploads the image to the server and the responseText is the correct path to the image. I did a console.log on the .src of the id AFTER the I plugged in the new image and the .src is correct BUT, it never changes in the elements tab in Chome inspect. It also works fine BEFORE I call uploadFormInfo().
I've tried and number of things (sending a separate request header for the uploadFile) and nothing works.
I'm stumped.

ajax -> save as dialog before downloading

I am programming an embedded Device in C with a webserver. One Task is to download files from this devices. I want to Download serveral files at once, so i created an ajax-request, which using POST-Request and a bunch of filenames to return a zip-file (i create these zip-file on my own on the device). Everything works fine, but the dialog save as appears after the whole zip-file was transmitted.
At server-side the device is sending the 200 OK-, Content-Type: application/octet-stream- and Content-Disposition: attachment; filename="testzip.zip"-headers.
At client-side i using this javascript-code(got this from stackoverlfow: Handle file download from ajax post):
function downloadFiles(filenames) {
var xhr = new XMLHttpRequest();
xhr.open('POST', /file-save/, true);
xhr.responseType = 'arraybuffer';
xhr.onload = function () {
if (this.status === 200) {
var filename = "test.zip";
var type = xhr.getResponseHeader('Content-Type');
var blob = new Blob([this.response], { type: type });
var URL = window.URL || window.webkitURL;
var downloadUrl = URL.createObjectURL(blob);
// use HTML5 a[download] attribute to specify filename
var a = document.createElement("a");
a.href = downloadUrl;
a.download = filename;
document.body.appendChild(a);
a.click();
setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); // cleanup
}
};
xhr.send(filenames);
}
The if-statement if (this.status === 200) is reached, when the whole file is transmitted. If the size of the file is small, there is not a problem, because the user isn't recognizing the lack of time. But is the file about 50MB the user can't see any download although the file is downloading. In my opinion the reason is a.click(), because the click-method imitades the begin of the download.
Is there sombody who can help me out with a solution or some hints?
By the way, jquery isn't an option!.
Thanks for any help
EDIT: my goal is to download a file like on every webpage with large files, where i get a dialog with the location to save and i can see the download-progress.
SOLUTION(Hint from Herr Derb):
function downloadFiles(filenames) {
var xhr = new XMLHttpRequest();
xhr.open('POST', /file_save/, true);
xhr.onload = function () {
if (this.status === 200) {
var mydisp = xhr.getResponseHeader('Content-Disposition');
var save_response = xhr.responseText;
var var_json_format = JSON.parse(save_response);
/* check for errors */
if(var_json_format["error"]) {
return;
} else {
status = _.findWhere(var_json_format["link"], {id : 'status'}).value;
download_id = _.findWhere(var_json_format["link"], {id : 'download_id'}).value;
}
if(status != "active") {
return;
}
var filename = "test.zip";
var downloadUrl = "/file_save/" + download_id;
var a = document.createElement("a");
a.href = downloadUrl;
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); // cleanup
}
};
xhr.send(filenames);
return;
}
Your first request should only create the zip file on your server and return a link to reach it. After you received that link on the client site, simply execute it. This way, everything will happen as you desire, as it will be a regular file download.
And ss soon the download is finished, your free to delete the file again.

Renaming an image created from an HTML5 canvas

I have made a simple canvas and save it as an image. I have done this with the help of this code:
var canvas = document.getElementById("mycanvas");
var img = canvas.toDataURL("image/png");
and pop up the created image with this:
document.write('<img src="'+img+'"/>');
But its name is always a weird one. I want to rename the image name like faizan.jpg etc. How can I do this?
To put it simply, you can't. When you call the toDataURL method on an HTMLCanvasElement it generates a string representation of the image as a Data URL. Thus if you try to save the image, the browser gives it a default filename (e.g. Opera saves it as default.png if the Data URL was a png file).
Many workarounds exist. The simplest one is to make an AJAX call to a server, save the image on the server-side and return the URL of the saved image which can then be accessed and saved on the client-side:
function saveDataURL(canvas) {
var request = new XMLHttpRequest();
request.onreadystatechange = function () {
if (request.readyState === 4 && request.status === 200) {
window.location.href = request.responseText;
}
};
request.setRequestHeader("Content-type","application/x-www-form-urlencoded");
request.open("POST", "saveDataURL.php", true);
request.send("dataURL=" + canvas.toDataURL());
}
To save the image on the server side, use the following PHP script:
$dataURL = $_POST["dataURL"];
$encodedData = explode(',', $dataURL)[1];
$decodedData = base64_decode($encodedData);
file_put_contents("images/faizan.png", $decodedData);
echo "http://example.com/images/faizan.png";
Got this working 100%! Just had to do a little debugging to the above answer. Here's the working code:
The JavaScript:
var saveDataURL = function(canvas) {
var dataURL = document.getElementById(canvas).toDataURL();
var params = "dataURL=" + encodeURIComponent(dataURL);
var request = new XMLHttpRequest();
request.open("POST", "/save-data-url.php", true);
request.setRequestHeader("Content-type","application/x-www-form-urlencoded");
window.console.log(dataURL);
request.onreadystatechange = function () {
if (request.readyState === 4 && request.status === 200) {
window.console.log(request.responseText);
}
};
request.send(params);
}
/scripts/save-data-url.php:
<?php
$dataURL = $_POST["dataURL"];
$encodedData = explode(',', $dataURL);
$encodedData = $encodedData[1];
$decodedData = base64_decode($encodedData);
file_put_contents("images/log.txt", $encodedData);
file_put_contents("images/test.png", $decodedData);
echo "http://www.mywebsite.com/images/test.png";
?>

Categories

Resources