• Guest, before posting your code please take these rules into consideration:
    • It is required to use our BBCode feature to display your code. While within the editor click < / > or >_ and place your code within the BB Code prompt. This helps others with finding a solution by making it easier to read and easier to copy.
    • Don't share a wall of code. All we want is the problem area, the code related to your issue.


    To learn more about how to use our BBCode feature, please click here.

    Thank you, Code Forum.

JavaScript Help with Upload javascript

chrisj

Coder
Thanks for all of your previous help.
I am testing this new code, where video is captured/recorded successfully. However, I don’t have the upload part correct. Nothing happens upon selecting the upload button:

HTML:
<button id="button1" onclick="startRecording()">Start</button>
<button id="button2" onclick="endRecording()">Stop</button>
<button id="fileupload">Upload File</button>
<video id="video" autoplay="autoplay" controls="controls" poster="/thumbnail.jpg" type="video/mp4" muted playsInline><source src="source.mp4" type="video/mp4"></video>

and the js:
JavaScript:
function supportsRecording(mimeType)
{
    if (!window.MediaRecorder)
        return false;
    if (!MediaRecorder.isTypeSupported)
        return mimeType.startsWith("audio/mp4") || mimeType.startsWith("video/mp4");
    return MediaRecorder.isTypeSupported(mimeType);
}

var video = document.querySelector('#video');

let blobs = [];
let stream;
let mediaRecorder;
async function startRecording()
{
    stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true });
    mediaRecorder = new MediaRecorder(stream);
    mediaRecorder.ondataavailable = (event) => {
       // Let's append blobs for now, we could also upload them to the network.
       if (event.data)
            blobs.push(event.data);
    }
    mediaRecorder.onstop = doPreview;
    // Let's receive 1 second blobs
    mediaRecorder.start(1000);
}
function endRecording()
{
    // Let's stop capture and recording
    mediaRecorder.stop();
    stream.getTracks().forEach(track => track.stop());
}
function doPreview()
{
    if (!blobs.length)
        return;
    // Let's concatenate blobs to preview the recorded content
    video.src = URL.createObjectURL(new Blob(blobs, { type: mediaRecorder.mimeType }));
}

//////////////////////////////////////////////////////////////////////////////////////////////////

async function uploadFile() {
    let formData = new FormData();
    formData.append("file", fileupload.files[0]);
    await fetch('/upload.php', {
      method: "POST",
      body: formData
    });
    alert('The file has been uploaded successfully.');
}


any assistance is appreciated
 

Mutiny

Active Coder
How is your uploadFile function being called? It doesn't appear anything actually ever calls it. Maybe you need to do:

HTML:
<button id="fileupload" onclick="fileUpload()">
 

chrisj

Coder
Thanks for your reply/help.

I have added:
HTML:
<button id="fileupload" onclick="fileUpload()">Upload</button>
and ran it.
In the Console it shows: "Uncaught ReferenceError: fileUpload is not defined at HTMLButtonElement.onclick".
Any help with how to define it is welcomed. Thanks again
 

Mutiny

Active Coder
Try changing async function uploadFile to function uploadFile, you don't need to asynchronously call that function since the user is pressing a button to trigger it.
 

chrisj

Coder
Much thanks for your reply. After making your suggested change I see:
"Uncaught SyntaxError: await is only valid in async functions and the top level bodies of modules"
Any additional guidance is appreciated
 

chrisj

Coder
Here is my latest code:
HTML:
<button id="button1" onclick="startRecording()">Start</button>
<button id="button2" onclick="endRecording()">Stop</button>
<button id="uploadFile" onclick="uploadFile()">Upload</button>
<video id="video" autoplay controls muted playsInline></video>

And the JS:
function supportsRecording(mimeType) {
if (!window.MediaRecorder) {
return false;
}
if (!MediaRecorder.isTypeSupported) {
return mimeType.startsWith("audio/mp4") || mimeType.startsWith("video/mp4");
}
return MediaRecorder.isTypeSupported(mimeType);
}

var video = document.querySelector("#video");

let blobs = [];
let stream, mediaRecorder, blob;

async function startRecording() {
stream = await navigator.mediaDevices.getUserMedia({
audio: true,
video: true,
});
mediaRecorder = new MediaRecorder(stream);
mediaRecorder.ondataavailable = (event) => {
// Let's append blobs for now, we could also upload them to the network.
if (event.data) {
blobs.push(event.data);
}
};
mediaRecorder.onstop = doPreview;
// Let's receive 1 second blobs
mediaRecorder.start(1000);
}

function endRecording() {
// Let's stop capture and recording
mediaRecorder.stop();
stream.getTracks().forEach((track) => track.stop());
}

function doPreview() {
if (!blobs.length) {
return;
}
// Let's concatenate blobs to preview the recorded content
blob = new Blob(blobs, { type: mediaRecorder.mimeType });
video.src = URL.createObjectURL(
blob,
);
}


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

function uploadFile() {
// create FormData
var formData = new FormData();
var request = new XMLHttpRequest;
formData.append("video-filename", blob.name);
formData.append("video-blob", blob);
request.open("POST", "/save1.php", true);
request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
request.send("data=" + formData);
}

everything works successfully above the ////////

here is the corresponding php:


PHP:
<?php
foreach(array('video', 'audio') as $type) {
if (isset($_FILES["${type}-blob"])) {

$fileName = $_POST["${type}-filename"];
$uploadDirectory = 'uploads/'.$fileName;

if (!move_uploaded_file($_FILES["${type}-blob"]["tmp_name"], $uploadDirectory)) {
echo(" problem moving uploaded file");
}

echo($fileName);
}
}
?>

Any help to determine what is preventing the upload, is appreciated
 

Mutiny

Active Coder
Do you get any errors when trying to upload? What do you see in your browser's network console, does a file upload request appear to start and then fail with a server error?
 

chrisj

Coder
Many thanks for your kind reply. I see no errors in console. However, in the meantime I have been told "you are sending stream as formdata and in server you are checking it as file, which will not work. You have to parse it from the object or you have send it as a file from ajax", which I don't know how to do. Any additional guidance is welcomed
 

Mutiny

Active Coder
I think you are trying to get the file using $_FILES when you should be getting it from $_POST. Treat the file just like any other form field, you should get a blob that contains the code for the file. You should be able to take that blob data and write it to the database or to the file system.
 

chrisj

Coder
Thanks again for your help, this uploads successfully now:
JavaScript:
function uploadFile() {
  // create FormData
  var fileType = 'video'; // or "audio"
var fileName = 'ABCDEF.webm';
  var formData = new FormData();
  var request = new XMLHttpRequest;
  formData.append(fileType + '-filename', fileName);
formData.append(fileType + '-blob', blob);
  request.open("POST", "/save1.php");
  request.send(formData);
}

The code I have posted in #1 successfully captures/records as stated, via desktop and mobile device (iPhone), but only, currently, uploads successfully via desktop. Any suggestion as to how it can be modified to upload successfully, via mobile too, would be very helpful. Thanks again
 

Mutiny

Active Coder
Do you get any errors on mobile? Does it fail to upload on both Android and iPhone, or just one? I know iPhones can be particularly tricky.

You might have to debug using a tool like LambdaTest (https://www.lambdatest.com/) so you can get the output of the mobile Javascript console. Unfortunately debugging via mobile really sucks.
 

chrisj

Coder
Thanks for your reply.
It appears to work with this code:

JavaScript:
      function uploadFile() {
      // create FormData
      var fileType = 'video'; // or "audio"
      var fileName = 'WXYZ.webm';
      var formData = new FormData();
      var request = new XMLHttpRequest;
      formData.append(fileType + '-filename', fileName);
      formData.append(fileType + '-blob', blob);
      request.open("POST", "/save1.php");
      request.onreadystatechange = function() {
      if(request.readyState==4) {
      alert(request.responseText);
      }
      }
      request.send(formData);
}

However, each upload replaces the previous file named WXYZ.webm.

I have this random name function code, it may too old to use, but I'd like to integrate it with the above code, but am not sure how/where to do that.
If I need to start another posting to ask this question, let me know. Otherwise the code is this:

JavaScript:
                    function getFileName(fileExtension) {
                        var d = new Date();
                        var year = d.getUTCFullYear();
                        var month = d.getUTCMonth() +1;
                        var date = d.getUTCDate();
                        return 'Record-' + year + month + date + '-' + getRandomString() + '.' + fileExtension;
                    }

                    function getRandomString() {
                        if (window.crypto && window.crypto.getRandomValues && navigator.userAgent.indexOf('Safari') === -1) {
                            var a = window.crypto.getRandomValues(new Uint32Array(3)),
                                token = '';
                            for (var i = 0, l = a.length; i < l; i++) {
                                token += a[i].toString(36);
                            }
                            return token;
                        } else {
                            return (Math.random() * new Date().getTime()).toString(36).replace(/\./g, '');
                        }
                    }

I look forward to any feedback/suggestions/solutions
 

Mutiny

Active Coder
@chrisj when you say the file is overwritten, that sounds like a server code problem in the "save1.php" file. What does the code for that look like?

I'm thinking you will need to update that file so the filename saved to the filesystem is unique, likely based on the current timestamp plus some other value, such as a unique ID per user.
 

chrisj

Coder
Thanks for your reply.
Regarding, "file is overwritten, that sounds like a server code problem", I think it's the javascript where each file has this name: WXYZ.webm
Code:
      function uploadFile() {
      // create FormData
      var fileType = 'video'; // or "audio"
      var fileName = 'WXYZ.webm';

Regarding, "so the filename saved to the filesystem is unique", yes, that's why I posted this code:

function getFileName(fileExtension) {
var d = new Date();
var year = d.getUTCFullYear();
var month = d.getUTCMonth() +1;
var date = d.getUTCDate();
return 'Record-' + year + month + date + '-' + getRandomString() + '.' + fileExtension;
}

function getRandomString() {
if (window.crypto && window.crypto.getRandomValues && navigator.userAgent.indexOf('Safari') === -1) {
var a = window.crypto.getRandomValues(new Uint32Array(3)),
token = '';
for (var i = 0, l = a.length; i < l; i++) {
token += a.toString(36);
}
return token;


any help with integrating the Randon Name code with the Upload File finction is appreciated.
 

Mutiny

Active Coder
Well, there are two ways to tackle the problem, either rename the file on the client (Javascript) or rename on the server (PHP). You want to be renaming on the server, as if someone can just pass in the same filename by editing your code, they can overwrite the file on your server.
 

chrisj

Coder
Thanks for your reply. I don't understand this sentence, however: "You want to be renaming on the server, as if someone can just pass in the same filename by editing your code, they can overwrite the file on your server". Can you please clarify?
 

Mutiny

Active Coder
Yeah, so because Javascript runs in the browser, everything it does is editable by the end user if they are tech-savvy enough. So, I can go to your site and read your code and see that you are changing the filename in your Javascript. I can also see that when your file is saved, there's a .php file that actually saves it to your server.

You need to make sure the PHP file is secure, you shouldn't rely on the Javascript, which anyone can edit, for security. So, if your PHP file receives a file with the same name as a previously uploaded file and just overwrites it, that's not secure.

Is your PHP file also verifying that the file users are uploading is actually a video file? Hackers could also circumvent your Javascript entirely and have the PHP file upload a shell script to your server, then they have control of everything. You need to be doing file validation on the PHP file that handles the file upload, which based on the fact that the file gets overwritten if the name is the same it sounds like proper verification may not be in place.
 

chrisj

Coder
Many thanks for your informative reply. I've tried to add some file validation in my php (I added: "// make sure that one can upload only allowed audio/video files" and the next 12 lines), but now when I upload I get this message "Invalid file extension", when the file is webm. Any help with resolving this is appreciated.

PHP:
<?php
foreach (array('video', 'audio') as $type) {
    if (isset($_FILES["${type}-blob"])) {

        $fileName = $_POST["${type}-filename"];
        $uploadDirectory = 'uploads/' . $fileName;

            // make sure that one can upload only allowed audio/video files
            $allowed = array(
                'webm',
                'wav',
                'mp4',
                'mov'
    );

    $extension = pathinfo($filePath, PATHINFO_EXTENSION);
    if (!$extension || empty($extension) || !in_array($extension, $allowed)) {
        echo 'Invalid file extension: '.$extension;
        return;
    }

        if (!move_uploaded_file($_FILES["${type}-blob"]["tmp_name"], $uploadDirectory)) {
            echo (" problem moving uploaded file");
        }
    }
}
 

chrisj

Coder
Thanks again for your reply. Can you help me figure out "what the extension that your call to pathinfo is returning when you try to upload a file". I believe I posted all the pertinent code.
 
Last edited:

Top