Play local (hard-drive) video file with HTML5 video tag? - html

I want to achieve the following.
<video src="file:///Users/username/folder/video.webm">
</video>
The intent is that the user will be able to select a file from his/her hard drive.
And the reason for not uploading is of course transmission costs and storage quota. There will be no reason to save the file.
Is it possible?

It is possible to play a local video file.
<input type="file" accept="video/*"/>
<video controls autoplay></video>
When a file is selected via the input element:
'change' event is fired
Get the first File object from the input.files FileList
Make an object URL that points to the File object
Set the object URL to the video.src property
Lean back and watch :)
http://jsfiddle.net/dsbonev/cCCZ2/embedded/result,js,html,css/
(function localFileVideoPlayer() {
'use strict'
var URL = window.URL || window.webkitURL
var displayMessage = function(message, isError) {
var element = document.querySelector('#message')
element.innerHTML = message
element.className = isError ? 'error' : 'info'
}
var playSelectedFile = function(event) {
var file = this.files[0]
var type = file.type
var videoNode = document.querySelector('video')
var canPlay = videoNode.canPlayType(type)
if (canPlay === '') canPlay = 'no'
var message = 'Can play type "' + type + '": ' + canPlay
var isError = canPlay === 'no'
displayMessage(message, isError)
if (isError) {
return
}
var fileURL = URL.createObjectURL(file)
videoNode.src = fileURL
}
var inputNode = document.querySelector('input')
inputNode.addEventListener('change', playSelectedFile, false)
})()
video,
input {
display: block;
}
input {
width: 100%;
}
.info {
background-color: aqua;
}
.error {
background-color: red;
color: white;
}
<h1>HTML5 local video file player example</h1>
<div id="message"></div>
<input type="file" accept="video/*" />
<video controls autoplay></video>

That will be possible only if the HTML file is also loaded with the file protocol from the local user's harddisk.
If the HTML page is served by HTTP from a server, you can't access any local files by specifying them in a src attribute with the file:// protocol as that would mean you could access any file on the users computer without the user knowing which would be a huge security risk.
As Dimitar Bonev said, you can access a file if the user selects it using a file selector on their own. Without that step, it's forbidden by all browsers for good reasons. Thus, while his answer might prove useful for many people, it loosens the requirement from the code in the original question.

Ran in to this problem a while ago.
Website couldn't access video file on local PC due to security settings (understandable really)
ONLY way I could get around it was to run a webserver on the local PC (server2Go) and all references to the video file from the web were to the localhost/video.mp4
<div id="videoDiv">
<video id="video" src="http://127.0.0.1:4001/videos/<?php $videoFileName?>" width="70%" controls>
</div>
<!--End videoDiv-->
Not an ideal solution but worked for me.

I tried to simplify the answer of Dimitar Bonev as much as I could.
<html>
<head>
<title>HTML5 local video file player example</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body>
<h1>HTML5 local video file player example</h1>
<input type="file" accept="video/*"><br>
<video controls></video>
<script type="text/javascript">
(function localFileVideoPlayer() {
'use strict'
var playSelectedFile = function(event) {
var file = this.files[0]
var URL = window.URL || window.webkitURL
var fileURL = URL.createObjectURL(file)
var videoNode = document.querySelector('video')
videoNode.src = fileURL
}
var inputNode = document.querySelector('input')
inputNode.addEventListener('change', playSelectedFile, false)
})()
</script>
<p>I hereby signed confess solemnly that I have no idea what this code does. But it now works.
<p>Firefox Lubuntu 18.03
<p>Simplified: `http://jsfiddle.net/dsbonev/cCCZ2/` `https://stackoverflow.com/users/691308/dimitar-bonev`
</body>
</html>

Related

Fortify Often Misused: File upload Issue

<!DOCTYPE html>
<html>
<head>
<script>
function fileValidation(fileInput) {
var filePath = fileInput.value;
// Allowing file type
// First check file type
const fileTypes = [
".pdf",
"file"
];
if (!fileTypes.includes(fileInput.type)) {
console.log("Invalid file input")
fileInput.value = '';
return false;
}
// Second check file content
var fileContent = fileInput.files[0];
if (fileContent) {
var reader = new FileReader();
reader.readAsText(fileContent);
reader.onload = function (evt) {
console.log(reader.result)
}
reader.onerror = function (evt) {
console.log(reader.error)
}
}
// Third check file size
const fileSize = fileInput.files[0].size / 1024 / 1024; // in MiB
if (fileSize > 2) {
console.log('File size exceeds 2 MiB');
return false;
}
}
</script>
</head>
<body>
<!-- File input field -->
<label for="botFile">File upload</label>
<input type="file" id="botFile" onchange="fileValidation(this)" maxlength="255" name="botFile" accept=".pdf" />
</body>
</html>
Fortify shows this recommendation to fix the issue
Do not allow file uploads if they can be avoided. If a program must accept file uploads, then restrict the ability of an attacker to supply malicious content by only accepting the specific types of content the program expects. Most attacks that rely on uploaded content require that attackers be able to supply content of their choosing. Placing restrictions on the content the program will accept will greatly limit the range of possible attacks. Check file names, extensions, and file content to make sure they are all expected and acceptable for use by the application.
Result:
Tried several other fixes to resolve this Issue. But fortify doesn't eliminate the issue.
Can anyone please suggest the fix/solution ?

exporting .txt files in html, and then importing it afterwards

So im making a website, and one of its core features I need to get working is getting the web page to export a mundane .txt file containing all the content from the forms I have.
Once that works, I also need to figure out how to import that same file back into the website and have it automatically fill in the text boxes.
How can I go about doing this?
Your question is kind of broad and doesn't show much research effort on your part. It's good form to have a go and then come here when you run into a problem, rather than just ask us to solve your problem for you. Despite that, I'll try to give you some pointers. :)
I recently had a requirement to make a button to download the contents of a div. I made a gist for future reference. You can probably adapt it to your purpose.
Basically what I did was assign a click handler to a HTML button marked 'Download'. When the button is clicked, I create a temporary anchor element on the page and set its href to the contents of the div and then programmatically click on the anchor to fire the download and finally removing the temporary anchor from the page. There's a fallback for Internet Explorer with a different method. I adapted this code from an SO answer some time ago.
var downloadButton = document.getElementById('downloadButton');
downloadButton.addEventListener('click', function () {
//get the contents of the div
var contents = document.getElementById('someDiv').innerHTML;
if (contents.length = 0) {
return;
}
var filename = 'some-filename.txt';
if (navigator.msSaveBlob) { // IE
navigator.msSaveBlob(new Blob([contents], { type: 'text/plain;charset=utf-8;' }), filename);
} else {
var link = document.createElement('a');
link.setAttribute('download', filename);
link.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(contents));
document.body.append(link);
link.click();
document.body.removeChild(link);
}
});
As for your next requirement, upload the file and importing the data, I'll direct you to the HTML5 Rocks - file handling tutorial.
I just had a crack at a quick file uploader and I have it dumping the file contents to the console. You could, instead, parse the file contents and add the data back to your form elements as required. Here's my test code:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<title>Test Page</title>
<script>
function handleFileSelect(evt) {
var files = evt.target.files; // FileList object
// Loop through the FileList
for (var i = 0; i < files.length; i++) {
var reader = new FileReader();
// when the file has been read, print the contents to the console
reader.onloadend = function (evt) {
if (evt.target.readyState == FileReader.DONE) {
console.log(evt.target.result);
}
};
var text = reader.readAsText(files[i]);
}
}
document.addEventListener('DOMContentLoaded', function () {
document.getElementById('files').addEventListener('change', handleFileSelect, false);
});
</script>
</head>
<body>
<input type="file" id="files" name="files[]" multiple />
</body>
</html>

Can I use a local file as a source in a live page?

I like to use JSFiddle when designing a new interface because I find it convenient for various tools within. I'm working on the front end of a site where I want to use a video, and unlike an image, I cant just throw it up on imgur and link to it for free instant hosting while I fiddle with the interface design.
So I want to know if I can somehow use a local file on my PC as the source for an HTML video element hosted on a live site. Obviously this is trivial to do with a web project being worked on on my Desktop, but I'm not sure it can be done on a live test.
For example this would work on a page I open from my desktop, living on my PC:
<video id="Video-Player">
<source src="../movie.mp4" type="video/mp4"/>
</video>
But I don't know whether I can do the equivalent with a page living on the web.
Here's how to allow a user to select an image from their local machine. This should get you started in the right direction.
Add a file input button in the HTML
<input type="file" id="file-btn"/>
and the corresponding handler
document.getElementById('file-btn').addEventListener('change', function(e){
readFiles(e.target.files);
})
Then the code to read the files
function readFiles(files){
files = [].slice.call(files); //turning files into a normal array
for (var file of files){
var reader = new FileReader();
reader.onload = createOnLoadHandler(file);
//there are also reader.onerror reader.onloadstart, reader.onprogress, and reader.onloadend handlers
reader.readAsDataURL(file);
}
}
Now, I've only done this with images, but this is how I read the image data.
function createOnLoadHandler(file){
console.log('reading ' + file.name + ' of type ' + file.type)
function onLoad(e){
var data = e.target.result
display(data);
}
return onLoad
}
function display(data){
var img = document.createElement('img');
img.src = data;
var context = canvas.getContext('2d')
context.clearRect(0, 0, WIDTH, HEIGHT);
context.drawImage(img, 0, 0, WIDTH, HEIGHT);
}
Here is a demo of the above code.
As a side note, if you try to read images from another domain you'll run into cross origin policy issues. I would think the same problem exists for videos as well.

reading text files in html5 + javascript, result is browser dependant

I've been going over this for hours now, looking through different options on the web trying to understand -and not just replicate- how to load a text file. I couldn't get to work ANY of the examples I found, that is, until I changed from chromium to firefox. As an example, the code in stackoverflow question: HTML5 File api, reading in an xml/text file and displaying it on the page? which I write here for simplicity:
<!DOCTYPE html>
<html>
<head>
<title>reading xml</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<input type="file" id="files" name="files[]" multiple />
<output id="list"></output>
<script>
function handleFileSelect(evt) {
var files = evt.target.files; // FileList object
// Loop through the FileList
for (var i = 0, f; f = files[i]; i++) {
var reader = new FileReader();
// Closure to capture the file information.
reader.onload = (function(theFile) {
return function(e) {
// Print the contents of the file
var span = document.createElement('span');
span.innerHTML = ['<p>',e.target.result,'</p>'].join('');
document.getElementById('list').insertBefore(span, null);
};
})(f);
// Read in the file
reader.readAsText(f);
// reader.readAsDataURL(f);
}
}
document.getElementById('files').addEventListener('change', handleFileSelect, false);
</script>
</body>
works great on firefox. I cannot get it to work in chromium. What am I missing?! thanks.
I'm using Chromium 18.0.1025.168 (Developer Build 134367 Linux) Ubuntu 11.10
Could it be this?
for (var i = 0, f; f = files[i]; i++) {
Shouldn't your second part be a conditional. Something like i < files.length?
For security reasons, to load local files I have to call chromium from the command line using:
chromium-browser --allow-file-access-from-files
ATENTION: you have to close all chromium windows for this to take effect.
Just lost about four hours because of this...

localStorage doesn't retrieve values after page refresh

I'm trying to test out html5 localStorage feature. For some reason, whenever I try to retrieve a value from storage after refreshing the page, I only get null values returned. (If I try retrieving the values in the same function that I set them in, then I can properly retrieve them).
One thing: the html/javascript that I'm loading is being requested from the local disk (for example, I'm using the string: "file:///C:/testLocalStore.html" to browse to the file, instead of requesting it from a web server. Would this cause the localStore problems that I'm seeing?
(I'd like to post the full code example, but I'm having some problems with the formatting. I'll post it shortly).
<html> <head> <title>test local storage</title>
<base href="http://docs.jquery.com" />
<script src="http://code.jquery.com/jquery-1.3.js"></script>
<script type="text/javascript">
function savestuff()
{
var existingData = localStorage.getItem("existingData");
if( existingData === undefined || existingData === null )
{
// first time saving a map.
existingData = $("#mapName").val();
}
else
{
existingData = existingData + "," + $("#mapName").val();
}
localStorage.setItem("existingData", existingData);
// test is non-null here, it was properly retrieved.
var test = localStorage.getItem("existingData");
}
$(document).ready( function init()
{
// existing data is always null.
var existingData = localStorage.getItem("existingData");
if( existingData !== null )
{
var existingDataListHtml = existingData.split(",");
existingDataListHtml = $.each(existingData, function(data) {
return "<li>" + data + "<\/li>";
});
$("#existingData").html("<ul>" + existingDataListHtml + "<\/ul>");
}
} );
</script>
</head> <body>
<form id="loadFromUser" onsubmit="savestuff();">
<input id="mapName" type="text">
<input type="submit" value="save">
</form>
<div id="existingData"> </div>
</body> </html>
Yes, loading the file locally means that it doesn't have an origin. Since localStorage is uses the same-origin policy to determine access to stored data, it is undefined what happens when you use it with local files, and likely that it won't be persisted.
You will need to host your file on a web server in order to have a proper origin; you can just run Apache or any other server locally and access it via localhost.