I've searched whether it is possible for JavaScript to differentiate whether the file is a video or image. However there were just multiple sites showing how to accept those types on the input tag.
However, what I need is how can JS determine the file type, then display the file URL in either an image or the video HTML tag.
Currently when a user is to upload a file, I have used this as my file upload input:
<input accept="image/*,video/*" multiple="multiple" onchange='openFile(event)' style="display: none" type="file" id="selectedFile" />
But instead of the user having to "select" whether it is a video or image, the browser can find the file type and assign to file source to the right source element.
My current code which uploads the file creates a data:url for the image or video that the user uploads and sends it through a socket which displays to others presently on the site as shown below:
var openFile = function(file) {
var input = file.target;
var reader = new FileReader();
reader.onload = function() {
try {
var file = reader.result;
Toast.fire({
title: 'Uploading your File...',
text: " ",
didOpen: () => {
Swal.showLoading()
},
})
socket.emit('message', `
//
//
// However how can it differentiate which tag to use and use the uploaded data URL??
//
//
<video controls autoplay="1" alt="Video Uploaded" style="cursor: zoom-in; border-radius: 4px; width: 16rem" src="${file}">
<img alt="Image Uploaded" style="cursor: zoom-in; border-radius: 4px; width: 16rem" src="${file}">
`);
}
catch (err) {
}
};
reader.readAsDataURL(input.files[0]);
};
*I'm not using a blob for the file as it will not show for other users when sent through the socket. I also would rather use on file input button as I'm trying to keep things as simple for the user as possible.
TL;DR:
User clicks a "Upload file" button
User can upload either video or image files from the same input button
JS create a dataURL link and finds the file format
JS assigns which attribute tag ( or ) the file will display in
Sends through socket for others to see
Really appreciate if anyone can help! Thanks.
the reader.result contains MIME type of the file, from it you can detect if it's image or video or something else:
var openFile = function(file) {
var input = file.target;
var reader = new FileReader();
reader.onload = function() {
try {
var file = reader.result;
Toast.fire({
title: 'Uploading your File...',
text: " ",
didOpen: () => {
Swal.showLoading()
},
})
var match = reader.result.match(/^data:([^/]+)\/([^;]+);/) || [];
var type = match[1];
var format = match[2];
if (type == "video")
{
socket.emit('message', `
<video controls autoplay="1" alt="Video Uploaded" style="cursor: zoom-in; border-radius: 4px; width: 16rem" src="${file}">
`);
}
else if (type == "image")
{
socket.emit('message', `
<img alt="Image Uploaded" style="cursor: zoom-in; border-radius: 4px; width: 16rem" src="${file}">
`);
}
}
catch (err) {
}
};
reader.readAsDataURL(input.files[0]);
};
With it, you also can fine tune it by filtering based on format (it's not exactly a file extension, but rather a type of image/video, for example .mov = quicktime).
Related
I wish to display an input element's selected image. Can this be performed on a local file, accessing the image client side, or would I need to upload the image to a server?
Here's my attempt in React. I can access the correct file name from the input element using inputElem.files[0].name. As soon as I am trying to set an image element to it, the broken image icon is displayed, and no error is surfaced.
const App = () => {
// state to keep track of img elements src. The default works fine.
const [imgSrc, setImgSrc] = useState('/images/test.jpg')
function handleImgUpload() {
const url = '/images/' + e.target.files[0].name
setImgSrc(url)
console.log(url) // /images/26e3e793-98f5-4720-9f82-8963276d5e27.JPG
}
function handleImgLoadSuccess() {
console.log('image loaded!')
}
function handleImgLoadError() {
console.log('image not loaded')
}
return (
<div>
<div>
<label htmlFor="img">Select an image:</label>
<input
type="file"
id="img"
name="img"
accept="image/png, image/jpeg"
onChange={(e) => handleImgUpload(e)}
/>
</div>
<img
src={imgSrc}
alt="Your upload"
onLoad={handleImgLoadSuccess}
onError={handleImgLoadError}
/>
</div>
)
}
In the console, however, the url seems to be correct.
<img src="/images/26e3e793-98f5-4720-9f82-8963276d5e27.JPG" height="100" width="200" alt="Input" class="jsx-855240488">
Hey – I see what you're trying to do, but it doesn't look like this will work. You need to create a new file reader.
const showTempImage = (e) => {
const file = e.target.files[0];
const img = document.createElement("img");
const reader = new FileReader();
reader.addEventListener('load', (e) => {
img.src = e.target.result;
});
reader.readAsDataURL(file);
// Append the img tag to the dom somewhere
}
This did the trick by creating a correct blob url.
const inputImg = e.target.files[0]
const url = URL.createObjectURL(inputImg)
// blob:http://localhost:3000/test-img.jpg
The resulting file stays in memory and needs to be removed in order to create memory leaks.
URL.revokeObjectURL(url)
This also seems to be accomplishable with FileReader, though there are differences.
I have an image with base64 url as src. I would like to send this image to the server using an input file (with a form).
So, i need to convert an img tag to an input file.
I am using the plugin Croppie to crop an image. Then, the result is writen in an img tag.
I have tried to convert the img tag into a File. But then i dont know how to convert the file to an input file.
<div>
<label for="img">Image</label><input type="file" name="img" id="img" value=""/>
</div>
<div>
<img id="outImg" />
<input type="file" name="imgtbn" id="imgtbn" value=""/>
</div>
document.getElementById('img').onchange = function (evt) {
var output = document.getElementById('outImg');
output.src = URL.createObjectURL(evt.target.files[0]);
if(this.c!=undefined)
{
this.c.destroy();
}
var el = document.getElementById('outImg');
this.c = new Croppie(el, {
viewport: { width: 300, height: 300 },
boundary: { width: 900, height: 300 },
showZoomer: false,
enableOrientation: true,
update: function (data) {
this.result('base64').then(function(dataImg) {
$('#imgCropped').attr('src', dataImg);
img = document.getElementById('imgCropped');
fetch(img.src)
.then(res => res.blob())
.then(blob => {
file = new File([blob], 'file', blob)
document.getElementById('imgtbn').file = file;
});
})
}
});
};
I would like to have an input file filled with the cropped image.
Thank you for your time.
You can't. Not only can you not use base64 in a file tag, but only an actual file, but you can't even set the value of a file input in Javascript at all. It's a security issue.
But why do you want to? If you've got the file encoded as base64 already, any text input is fine for sending it to the server. I'd probably use a <input type="hidden"> because it doesn't make sense to display the code. And if you want a preview, use an img tag.
As Amunium said, file inputs are read-only.
Saving the base64 image to a hidden input is the best way to do it.
One can empty file input values programmatically, but they will still be submitted; though empty.
There is a barebones explanation on how to get this done in a simple way.
I am creating a small html5 app that will allow users to change color properties of some elements. I want to give the user the option to save their changes and then upload them on later occasion (without registration). For this, I added a button that produces a text file of their properties, I want to add a button that will allow them to upload the file, I created a file picker dialog,
<label>
<input class="button"
type="file"
name="input-name"
style="display:none;"
onchange="read(event)"/>
<span id="input-file" >Select File</span>
</label>
But I can't figure how do I open this file in javascript and process its content. I know this should be similar to this
function read(evt){
var file = document.getElementById("input-file");
//checking for file reader
if (window.File && window.FileReader && window.FileList && window.Blob){
var r = new FileReader();
r.readAsText(file);
} else{
alert("Browser not supported");
}
}
But this doesn't work because file above is not the path to the file but the object. How do I get the path to the file? Is there a better way to do this?
You can read files via the File API, but you can't save them. You can create windows containing the text you want to save and then let the user save it, but it's a pain both when saving and loading.
Fortunately, for what you're talking about, you don't want files.
Instead, store the color preferences in web storage, specifically localStorage:
Loading (e.g., on page load or whenever):
var savedColor = localStorage.getItem("saved-color");
if (savedColor == null) {
// There wasn't one, use a default
}
Saving:
localStorage.setItem("saved-color", savedColor);
(localStorage in the above isn't a placeholder or anything; it's a global that's present on browsers that support local storage, which is [just about all of them2.)
Web storage values are always strings. You can use JSON if you need to store complex things.
Assuming your text file is in JSON (stringified format), i.e. your file.txt contains {"primary":"green","secondary":"#FF0000"}
<input type="file" id="file-picker" accept="text/plain" />
/*
Assuming JSON format in the text file - e.g:
var colors = {
primary: 'green',
secondary: '#FF0000'
}
JSON.stringify(colors);
output: '{"primary":"green","secondary":"#FF0000"}'
*/
var fileInput = document.querySelector('#file-picker');
function readFileJSON(file) {
return new Promise(function(resolve) {
var reader = new FileReader();
reader.onload = function(e) {
try {
resolve(JSON.parse(e.target.result));
} catch(ex) {
throw ex;
}
};
reader.readAsText(file);
});
}
fileInput.addEventListener('change', function(e) {
var file = e.target.files.item(0);
if (!file) {
return;
}
readFileJSON(file).then(function(colors) {
console.log('Colors:', colors);
});
});
JSBIN: https://jsbin.com/weriguhato/edit?html,js,output
Today I upload a picture using a simple button (id: "imageUpload") to upload a file. Evthg works perfectly. A thumb of the picture is then visible in "thumb1".
I would like to upload a picture also by clicking the div "preview1".
Here is my code with what I tried :
<input type="file" id="imageUpload">
<div class="preview1 slide" onclick="document.getElementById('imageUpload').click();">
<div id="thumb1" class="thumb"></div>
</div>
and the js :
new AjaxUpload('imageUpload', {
action: "upload",
name: 'userfile',
onSubmit : function(file, extension){
do some work..
},
onComplete: function(file, response) {
do some work..
}
});
Result :
When I click on "preview1", a window open to select a file : OKAY
but then the file is not uploaded (no thumb preview), and only the name of the file appear on the right of "imageUpload" :
Any idea ?
If I am understanding you correctly, you are looking to have a picture thumbnail appear on file upload. This might help you
How to generate a thumbnail image after adding an image inside an input type="file" in a form and submitting them both on the same form
Recycled from user: Che-azeh:
function previewFile() {
var preview = document.querySelector('img');
var file = document.querySelector('input[type=file]').files[0];
var reader = new FileReader();
reader.onloadend = function () {
preview.src = reader.result;
}
if (file) {
reader.readAsDataURL(file);
} else {
preview.src = "";
}
}
<input type="file" onchange="previewFile()"><br>
<img src="" height="200" alt="Image preview...">
For context, I'm trying to create a "click image" file uploader. Initially there is a default image, which I then click. I trigger a file upload, and the user picks an image file they want. Then I will set the image to replace the default (and do other things with it later). Right now, the front end looks something like this:
<div class="right-preview">
<input type="image" src="img/logo.png" height="240px" width="240px" ng-click="uploadImage('right-image')" id="upload-right-image"/>
<input type="file" id="upload-right" style="visibility: hidden">
</div>
When the image is clicked, it triggers an upload action.
$scope.uploadImage = function(side) {
$image = $('#upload-' + side);
$fileInput = $('#upload-right');
$fileInput.change(function(changeEvent) {
var files = changeEvent.target.files;
for(var i = 0; i < files.length; i++) {
file = files[i];
console.log(file);
}
});
$fileInput.trigger('click');
}
When the change event is fired after the user finishes picking their file, I have the changeEvent and I know they've selected their file. Each of the files has some properties (like name and size) but I'm not seeing anything for accessing the raw data so I can set the src on my other element.
Am I just completely missing how to get the image data, or is there a better way to do this? I have no server (right now) to post this to. Perhaps there is a better way to approach this?
This link may be helpful to you - https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsDataURL
I took one method from that page and added some additional functionality to hide the file upload button and have the image placeholder trigger its click event.
$('#placeholder').click(function() {
$('#img-upload').trigger('click');
});
function previewFile() {
var preview = document.querySelector('img');
var file = document.querySelector('input[type=file]').files[0];
var reader = new FileReader();
reader.addEventListener("load", function () {
preview.src = reader.result;
}, false);
if (file) {
reader.readAsDataURL(file);
}
}
.hidden {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<img width="250" height="250" id="placeholder" src="http://place-hold.it/250x250&text='click to upload'">
<input class="hidden" type="file" onchange="previewFile()" id="img-upload">