45 056 How to use the file field type to upload a file in JCB
Amigo edited this page 2019-10-10 09:54:19 +02:00


Add/Upload A File Field To A Component

00:00:00 (Click on these time links to see Youtube video)

We want to add a file field to a component and upload a file and are going to use this Demo component. It got a few Admin Views and the area 'Look'. There is a Site View, 'Looks' and 'Looking'. I am going to add this field to the Look Admin View. First, the field needs to be created and we need to look at the steps that need to be implemented. 00:00:32 Currently, JCB does not out of the box address this. We might think of doing this maybe in the future but because of some of the security risks, it is best you do this yourself because then at least you are under control.

Fieldtypes - File - Shows attributes, values, some descriptions, info


If a file is uploaded the Fieldtypes you need to use already exist. So if you go to Fieldtypes, there is a field called 'File'. 00:01:32 Everything in here was taken from Joomla's documentation. It shows you a whole lot of attributes, their values, some of the descriptions, but also shows you where to get more info on this. It is always good to do that. We are in Form field. 00:02:00 Scroll down and there is the file field. It has this new 'accept' parameter, which is a nice little extra which has not been available when I first set it up. If yours does not have it, you will see that I have since added it. It is not showing up here.

Adding New Attributes


I might as well add it now and place it under 'Size', and add that new attributes. Select 'accept', the value and leave it to be in 'image' and it can be changed. Give it some information regarding the description. Copy that and place in here(see video). We got this new attribute set. Those of you running the latest release of JCB, might already have this there. It only gets added if you do a fresh install. It does not update the database with these values. 00:03:15 Save and close. We got a file typeset.

Beginning Of Setting Up The File Field Type


If we go to Fields and we select the file, you will see that it gives you the Field information and there is the new 'accept' attribute available to us. You will see that it is also showing up in the XML field definition. This is the beginning of setting up the File field type to your component. 00:03:55 Just call this name: 'image', and then here at the label we can just say 'File'. Call type: 'image'. Description: 'Choose an image from computer with maximum 100Kb'. Most of these other values can be removed. We will come back to this. Once we have added to the component and started looking at some of the other things that must be done. 00:04:34 This only steps A. There are 3 steps to take of which this is the easiest. Up in the top, we have Name: add 'image'. Save and close.

Add File Field Type - Image(file)


Now go to our Admin View, and that is this 'Look'. I'm going to go directly to its fields, I could add that File Field type. 00:05:21 Let's do it in the more area, add it in the bottom. Add 'Imag'e and we will see there are quite a few files. 'Image', it should say 'Image[file]'. That should do it. 00:05:50 Let's make the Alignment full width for now. Then in Order in Edit one. Save and close. If we should open the Admin View, we should see the new Field has been added and it is set to being in the Full Width in Tab, and 'More' in Tab.00:06:15 We could now compile the component as a beginning to see how it will work out. Compile it, and then install it. Then have a look at it. 00:06:39

Let us say create a new demo. Go to 'More'. Here we see the file. So it is telling us File(one). We have a problem, there are two fields with the same name 'image'. I will have to go change this. 00:07:06 I'm going to uninstall this. Then go back to the fields because it is the last one I have created. Let's go to the end, 'image', and lets change the name 00:07:36 to 'banner'. I think we will use 'banner' and we will call Name on top of the page also 'Banner'. The field type is 'file', but will use the label 'banner' and save and close.

Now let's try again. You know if you have 00:08:06 two of the same fields meaning exactly the same name JCB automatically calls the one image(one), the other one image(two), and that is not good practice. It usually does not come out right in events, especially with history, because it is only tracking one field. When it checks the history, that field name does not match any field. 00:08:34 When it comes to the history and the updating of the database automatically as you add new fields using the same field multiple times is not recommended.

Let's try this again. Install it. Now, we should see 'Banner'. 00:09:07 It got all the necessary information. Obviously this 600.00MB is set in your server. You can click Browse and select an Image. So I got this autumn_tree_forest_building_grass.jpg that has been selected and needs to add a Name. 00:09:33 That seems to be all that is necessary and then save.

Needs To Be A Server Side - Needs To Validate, Move, Check The File - Make Sure: It's The Correct File, Secure The File, and Then Place The Files Path Back Into Fields


As you can see when I saved the item, it did not upload anything. The file is not in my system and that is where all of you would end up. You have used file and selected the 00:10:14 'Banner', whatever you wanted to upload, and just nothing happened and that is because there needs to be a server-side which needs to validate the file, move the file, and check the file, and everything. Make sure that it is a correct file, secure the file, and then place the file's path back into this Field. 00:10:42 When it puts the value in the database, and it is that process which is to be custom coded. Let's go back to our component. One of the things I like to do before start coding anything is to look at what is going on especially if it is the first time I am doing it. Since many of you, this might be your first time. I am going to open this item, again and again, select our image.

Code Editor - Joomla Mount, Administrator, Components, Demo, Models, Look.php


Then having the image selected, then go to the code. I know where the code is for this website. I am going into my editor and to the Admin area of this component and of this view, this model, into where it saves the values. (Follow on video). Here is 'Joomla Mount', 'administrator', 'components', 'com_demo', and then models, and 'look.php'. Double click. Go to almost the bottom of the file. 00:12:13 Look for the save function. That is where we want to sort of poke. It is at this point where all the data from the browser is available to us and be able to access it. You could write the Helper class and put it into your Helper function, and use the same uploading class if you want to reuse it. You could also script it right in here. I like reusing scripts so the Helper class idea is more appealing because I put it there and everywhere I use this Fieldtype for file uploading, I just also use this helper class to deal with moving the data and using it.

Var_dump Some Values - One Is The available Data, Second One Is Getting The Input


We are going to var_dump some values just to the screen when we click save in the UI to see what happened. One is the actual $data that is available, and the other is this we get the $input. Check-in files, to see what we do have there in the input of the application. Save these changes then go back to the website and just click save. We have got a dump, now if yours does not look like this, it might be because you do not have XD bug installed on your server.

Add Some Formatting


You would then want to add some formatting, something like this 'echo <pre>', something like that should do it. Just to add some formatting that it does not bulge into one line. Since I have XD bug it is not necessary, so it does it for me. We have the data and we see that Banner is not even the data list, but that is ok. 00:14:43 Just scroll down, you will see we dumped a different set of data and if we scroll a little, it has a protected value called jform, name, type, tmp name, error, size, all that information. In the tmp name it has the actual file name 'banner' with its tmp location.

It creates a temporal location for the file. It tells us the type is image, a jpeg and also gives us the file name. This is the array that you would want to get hold of and 00:15:29 with whom you would want to make changes, move that image, give it a correct name back, after validating it and doing whatever sanitation is required. Then saving that value back into the banner data-position which should be in this first array. If it is not there you should just create it.

Get Function - Jform Where The Data Is


Going back to the code. There is a nice Get function. We can just say jform if you remember that is where the data is, and if we want all the values back as an array or that it should be null if none is existing. Save that and then just upload the file again to see how does it look. It should be done again because some of the previous values are gone. Click save again, and there is a little different array, But more useful and easier to parse.

Next Step - If Array Exist


And now we can take the next step to check this array exists. There is a function or a class in Joomla which already does all of this for you. Let's just copy some of those functions.

Copy Function 'getPackageFromUpload' - Adapt It To Our Needs - Change Function Name To 'myUploadFunction'


Let's copy the function and adapt it to our needs and just put it into our class. In components go to the installer, then, model, and then on install, and scroll down till you see one that says 'getPackageFromUpload'. 00:17:29 This is the function which is really ideal for the task. It takes care of a lot of sanitizing, it has a lot of error checks in it, and it should be useful for us in this case. We will take some stuff away and add our own short messages, so we do not have to depend on the INSTALLER MSG. Just copy this whole function(see video). So there are some key things I would like to change, for example, 00:18:23 change the function name and call it 'myUploadFunction' for now. We pass to it the input and do not want that to be done twice. 00:18:50 We know this is going to be 'jform', and we definitely do not want to have it 'raw', because it is an image. We want this to be an 'array' that we can check the values. 00:19:19 We can say here set 'uploads are not enabled in php'. We can take these messages and put them in here, because JCB is going to grab this once we put it into our component, and going to add it to our language files for our component, this is to make sure that it happens. We do not need the zlib because nothing is going to be unzipped. This part can be removed. (see video).

Checking If Userfile Is An Array


It is going to check if we got a set of files here. It is going to check if that ($userfile) is an !is_array. If it is not, it wants to say no file was selected or no file was uploaded. We can just type that in. If at this point we detect any errors, we want to erase those errors and break out of this upload. So let's see UPLOADERROR, WARNINGUPLOADERROR. I suppose we need to go look at these language strings in the language file of the installer to correctly translate these but I am not going to do that but just going to say error.

Checking The Upload Size


What needs to be checked here, is the upload size. We want to make sure that our upload size is what we expected. Is the maximum upload size too small in the php.ini, and that is really what is happening here. Again it will give an error saying 'file too large'. The same here, it is checking again, this time it first checked whether it is in the INI files. Here it checks the file size and that there is file size. We can again say 00:21:57 'Upload error' and you should just check what is the actual file language string and replace that with the English version.

Build An Appropriate Path, Create The Path, Create Temporal Source - Move File With Jfile Upload


We //Build appropriate paths. We take the filename, create the path and create this $tmp_src which is the source path and then we move the file with the JFile::upload. Now at this point, the file is being uploaded to the server. 00:22:34 There is still validation to do in our script that we just grabbed from the uploader class, we do this unpack. We do not need to unpack, we want to do some other things here which are more appropriate for our purpose.

'Unpack the downloaded package file' Replaced By A Little Function 'checkUpload'


First thing, is to move the get classes function up a few lines, and also make sure to have the folder class available in the case and then going to clean the name, so that there should not later be any issues. We still have what we had here before. This 'Unpack the downloaded package file' is going to be replaced with a short function which I wrote called 'checkUpload' and going to change this function as one of my functions which I have already adapted for other projects in the past. As you may see I have already moved this one out. 00:23:38 That one can stay like that. (See video)

Do A Little Check-up - Set To False Or True


Do a little check-up to make sure that the package which we are going to give back and which will be used to store in a database and all the rest is okay. Grab the result of this which is going to be true or false and check if it is false, and can say 'Upload failed'. Then do this check. Now we have this 'checkUpload' in place and are first going to get the format from the file.

Use Custom Script To Validate Our Format


We are going to use a little custom script here to validate our format. In my component I usually set formats that I allow. So it is a Global thing. That means in your component you would have to go and add in config drop down, with a list of Allowed Formats. To sort of sidestep that, instead of trying to explain all that, I am just going to go and remove this function here(see video). 00:25:07 I am going to remove that and just add some formats that I am okay with, '.jpg', '.jpeg', and '.png', and then '.gif'. 00:25:30 Those are fine, of course, because it is the file extension that we are checking here. A global value is not going to be used here, we are just going to use the fileFormat, allowedFormats, and then check, if this is a fileFormat in allowedFormat array. If it is not, then say 'Invalid file format' 00:26:27 There we go and it is going to error out, but with this error out some house cleaning is necessary.

Passes The Destination Where We Moved The File


I am going to also pass it the destination of where we have moved the file because that is where the file currently is. Here we got the temporal destination( $tmp_dest ) which is in the temporal path( 'tmp_path'), the temporal folder of the Joomla website. It is not where we want to end up. 00:27:02 It is just where we are going to keep the file until we are happy that it is safe. We got it in the temporal destination, we moved it up there, and now we checked if something happened. Do check the upload. Here if we find that this 'archivename' file 00:27:26 is problematic, we are going to have to remove it. We are going to have a new little class here. We are going to say removeFile. I think that is right. We are going to write this little removeFile in a moment. Here is a lot of validation on whether the user has permission to upload stuff. It can be removed because it is going to be a little bit beyond the scope of what is explained.

Pass A Package Back


Now I want to pass a package back which we are happy with, saying this is where our file is, and what its name is. We are going to do that. That is the directory, and that is the package name(see video). We are going to pass that back to the package since we have got the format and maybe you want to store that. 00:28:41 'format' could also be added to the array. Everything looks good. The package name, directory path, as well as the format and we will return that back as the package and we give the package back to the model. In the save function we are going to call this 'myLoadFunction'. 00:29:17 Pass it the 'input' field, the input value since we are already getting it, why get it again. We are going to pass that over here(see video). 00:29:44 Now all that needs to be done is over here instead of this function $input->files->get('jform',null,'array') we can now do the following: $this->myUploadFunction($input). I will end up with that '$userfiles' package information right in this variable, and then just exit out to see how that will look.

Create Remove File


We still need to create 'remove file', if we have a problem. Why do we need to remove the file? Well, all the way up till here(see video) the files are not on the server. It is somewhere in memory. 00:30:40 If something happens and we returned false here, we do not need to do anything, it is not really anywhere it is just going to disappear and the same happens to these other areas (See Video). But the moment this Move uploaded file $p_file = JFile::up;oad(tmp_src,$tmp_dest, false,true) is done, we are moving the file to the server, if that is true, it is on the server. When we pass the destination and the filename to the 'checkUpload', we already have the file on the server. 00:31:12 If it is then discovered that this file is not legitimate, we must remove it, or any other checks we do, even if it is something more complicated than this, it must be removed, because it is on the server. With this little remove function (>removeFile) some unnecessary trouble might be avoided I am going to sniper it up a bit because we have already up here the classes for the file in a folder, so it is not necessary to load that again.00:31:36 Then pass it the destination, which is the 'folder'.

All of this(see video) may be cleared out. We do not need this(folder) but only the package name. 00:32:04 Is it a file? Then delete, then if there is something not right, we are going to do path::clean and just check again and delete. This should remove the file from the server. Google it to test if something is wrong, and tweak it but this should be OK. We are going to pass the destination path, which is the one where we moved it, remember up here. 00:32:29 That's the same path we are passing all the way down to the 'removeFile' function and then it will clear it for us. If everything is fine and it does not need to, we are going to continue and pass it back to the package which will be returned to our save method.

Dump Code on GitHub as Gist


So all of this code that I just wrote, gets dumped on GitHub as a gist. This can be quickly coded. Copy it and paste stuff from other classes to get this working, but there is nothing really complicated. 00:33:23 The only thing that we did not go into is exactly what does cleaning do, and what does apply do and that kind of things. You can go through the Joomla libraries and check exactly what it does. But for the most part, it is just generic PHP functionality. That it would be enough to upload the file.


So let's see if it works. Back over here, if we click the X on top of the page, it will take us out of the item. We can just click 'Looks', then 'Name' and we would have again to select the image. There we have the image. Click save and see what happens. Oops, there is a bunch of errors. It indicates 'undefined index'.

I am just going to do another var_dump(input); Most possibly it needs to be done for each. It might want to upload more than one or we could force it to just use the first. Think this should do the trick. If it is an array we just want to grab the first value out of the array. 00:35:09 If you got multiple fields that are uploading files in the same view you need to change this little chunk ($userfile = array_values($userfiles)[0] because then you are going to have to deal with each of those files for each loop inside of this function which would mean that you could skip all these as they are Global to every one of them and then from about here(see video), you would add it for each loop. 00:35:39 Do not echo here, well you will not break out, you just grab the error into an array which you would eventually pass, targeting each specific package. Then return package, and all the successes as well as the errors and handle it somewhere else. So since we are just uploading one file, I am not going to do all that, only to grab that first value and work with that first value. 00:36:07 Go back and try again. Save. Again there is a problem. It should not be userfiles but userfile. 00:36:32

At last, we have the file on the server. These points should be removed(see video). Now the file is in our temporal folder. 00:37:03 It is on the server. We have the path and the name, and all those things.

Moving The File To Its Final Location


We can now move the file to its final location. We could deal with moving the file to its final location here in our save class, or we can again have another function in which we pass the $userfile value too, which then moves the file too where we would want every image file to go. Let me quickly type that out. Here in our package, is the file name, that is important, and we got the full path which is where the file currently is, and what format it is.

More Values - Instead Passing Userfile Pass The Whole Array


We could have more values in here(see video), if we want to, instead of just passing that userfile, pass the whole array, and change that(See video) to archive and add 'name', which means it is available. So instead of doing check we can then do $archive ['packagename']. Then $archive['dir'], and 00:38:42 $archive['format'], and return the $archive package.

Now we will have all the information at our disposal which has been used up here and of coarse the necessary changes should be done here( Please follow on video). Well, you know what the name is already there 00:39:13 so instead of package name we can just be satisfied with the name. We could call this //set directory $archive['full_path']. That will be the only information that is added which is new with these two values. Now our array looks full. 00:39:44 It got the 'type', the original temporal, which is obviously no longer there. Any 'errors' that might have come up, the 'size' of the file, the 'full path' and the 'format'. All that information is available. It may be decided which information should be kept as the 'size' of the file or the 'format'. 00:40:14 We just have one Name field column in the database called 'banner', in which the final information is placed. That information should be the path in relation to the image folder where this file is placed.

Using Constants


First, get some constants to use. This JPATH_ROOT will be used as it is always going to be the root path to our website. Then next, add the path to the images. It is where the image is going to be placed. I am going to copy JPATH_ROOT, and add the path, the relation to the root folder to the banner in the database. It is only that you will later know where the file is, then on the front end of the site, where you are going to use this value, you will have to get the value from the database. 00:41:33

It is still necessary to create the actual image html tag to load the image or whatever you are going to do with this file. You still need to code that, nothing of that is going to be done. You are going to have the path to exactly where the file is because you are storing it that way in the 'banner' column, that is the field. Here we are taking the root path 'JPATH_ROOT' and that exact value and we are moving the full path, which we have build up here, which is the current destination. 00:42:02 We are going to move it from the full path to the final destination. At this point, we have got the image on the server and are moving it to the correct location. We are storing the value in the database, and we are done with saving and uploading the actual value. 00:42:28That would be all that is required. In any of these steps, you might want to do some more things, be more secure, be more validating, because it is not only images you are going to upload. If you upload PDF, if you are uploading another kind of content, you are going to have to do some googling to anywhere in these steps, especially in this check upload area, to do the correct validation. 00:43:03 At this point the file is on your server, and you need to make sure that it is the right file. Now, this is not airtight because this checks that the file's type is one of these, the extensions. 00:43:22 It does not validate the file to being an image. There are more secure ways to do that. If you do use them, then on the server-side if your application is going to be running, with shared environments, it will cause problems because some of those functions are not available in all shared environments. 00:43:42 But if you want to be very specific, you could help the user along who uses your application to enable those functions on their server, and by that giving them extra security with uploading of files. 00:44:14 In general this sort of implementation is how most are doing it.

Successfully Saved - Show No File Detected - Might Show The File Currently In Database


Everything is moved into place and a trial run can be done. It has been saved successfully but no file selected is shown. We might want to show the file that is currently in the database, instead of this upload or show the upload still; but let's say someone decides to upload another one, that changes it, and remove the old one and adds the new one, and displays the little image as it is in the database. First, let see if it is in the database. 00:45:12 Our file is in the database, and it is set to be in /images/autumn_trees_forest_building_grass.jpg. Let's see if it was moved to the place. In the folder structure, open images, and click on images, then scroll down and see /images/autumn_trees_forest_building_grass.jpg. in its place.00:45:46 The actual image does now exist in the image folder, it has been uploaded and it is in the database, although the snippet says that it can not see it.

Grab Custom Scripting And Add It To The Component In JCB


Before we continue with that kind of custom scripting, we need to take what we have done so far and add it to JCB. We have done it in the IDE, and if we compile and install this component now, you will overwrite everything that you have written, and it will be gone. Let's go grab that custom scripting and add it to the component in JCB. (See video) We want to grab everything from my 'uploads function', 00:46:41 do 'check upload', 'remove file' and say 'cut' and then place that in the clipboard, and go to JCB, in the 'Look Admin Views' which is where all this is happening. If it is opened, there is a place called 'Custom Buttons'. You are going to say 'Yes'. 00:47:07

Then there is the PHP(controller method), nothing is going to be added there, but there is the PHP(model method), this is the place for us to add some script to the model. We are going to paste what we have cut, right in here, and in the PHP List View (controller method) nothing is added and also in this PHP List View (model method) nothing is added. 00:47:32 We are adding that which we have written to the model method, 'Add your PHP here!' is going to go into the model as 'methods'. This is the methods, that 'checkupload' is a method, that 'myUploadFunction' is a method. We want it to be available to the class from now on. 00:47:59 Further custom scripting is necessary to get it to remove an old file when a new one is uploaded. At this point, it will only add the new file and leave the old one. It could be that more files get added to the image folder, without it being removed. There is a removeFile function which makes it quite easy to fix it if you are familiar with PHP.

Adding the Script To The Save Method


Now we have to add the Script that needs to be added to the save method. Here is the Add PHP(save method - before data modelling). The value is in the data array. Return to the IDE, and scroll up to this little snippet upload the image because this is everything new. Let's just copy it and cut that as well and go back to the JCB interface, and paste it there. 00:49:23 In the Add PHP(save method - before data modelling), we have this little snippet that will be executed, and the same applies within the Custom Buttons area, we have in the PHP(model method) our classes that are being added. 00:49:45 If we open the item, that means after we have saved it, we want to take the value in this $data[banner]', and want to display it in the page. Now there are many ways to do this and since we already have this value, it should not be that hard.


JavaScript will be used to do this. We have 'Add JavaScript' to 'view file' or 'Add JavaScript' to the 'view footer'. So it may be decided where to add the Javascript. Do we want to add JavaScript in a file that gets included in the header of the document or does we want to add it to the bottom of the view as a snippet? That is what we want to do because we want to use PHP. We are going to do some PHP in Add JavaScript(view-footer) area. 00:50:50 Whereas in this Add JavaScript(view-file) area we cannot do PHP. So to show you exactly where this is going to come out, we are going to add a comment: add javaScript here, and I'm going to show you how we are going to do <?php//also workes?> 00:51:20 Save that. Go out and compile this component and install it and then go look at its code. In our save class, we have 'upload the image' and it is right. 00:51:56 Search for our function. There is our function, in the same class that has been added through the JCB interface. It was not lost.

It's not exactly the same place we originally placed it, but it is in the same class and it is what we wanted. We wanted those classes to be available to us. Now look at the view and see where is that JavaScript going to be added. Close images, then go to com_demo, view and look, and edit.php.00:52:31 We are looking at that specific view, and here is the javaScript. It has been added to our script area and I am able to do php echo in the script area, which is what we are going to do. 00:53:14 We are going to check whether that Banner Value is available to us on this page and use it to render the image in its appropriate place.

To Know Where The Values Are?


To know where the values are, we will go back to its view.html.php area. We see that it gets the $this->item and it places it in the item global class value. We have the value item. We can, therefore, check if the banner is in the item. What I will do that you can see what's happening. Copy and then I'm going to go back to the edit.view where we put our html. I'm going to say 00:54:09 ,<?php var_dump($this->item)?>; that specific value, and save. Let's go to the interface. We have to add the word 'jexit' and go a little bit up because we got a little fader, it's going to hide this and let's just take that out for now that we can see 00:54:44 what's going on and then let's refresh the page. We got it all broken that is fine. Let's take it to the top, we have added it here above everything, it should show now. Refresh, that is what we want to see. 00:55:11 It is publicly accessible, there is the banner value. We can check whether there is a value in this /images/autum trees forest building grass.jpg', whether it is a string and has a value because we know we are controlling that value. The user cannot manually add that value there. It needs to do it through the upload field. We can check whether that has a string, and if it does, we can create a little show the image 00:55:39 below its appropriate placement. That is how I get to see the value. If you are dealing with something similar, you can do this kind of poking into the result sets to see exactly where is what, how does it look and how do I get to it? Back in JCB we are going to say 00:56:12 (isset($this-item->banner), and if it is a string, use the helper class. We have a function in the helper class called 'checkString', to see whether it has a length and that it is a string. 00:56:36 Not an array or a Boolean or something like that. This is the way you can use the helper class, use [[[Component]]]Helper:: . If that is true, we want to load the image because then it exists. 00:57:01 We want to see where do we want to add this image, it is below the upload. I am going to have it show up like a normal image. We are going to do some jQuery. We are doing this <img src= and echo the item banner because we know it is a string and can add a class. You can target this class and make it nice with CSS, add CSS to view. 00:57:30 Add the class name that you are going to target with your CSS and do all kinds of nice things with it. You are going to have alt and banner. We are going to insert it after the banner field. It is to know what this value is(See video), we open one of those views, 00:57:57 and we drill down until we find our inspector, grab maybe the Banner label, then drill until we find the id_jform(banner). 00:58:13 We just add this after the control group, that it would look nice, fits in with the layout and I think it is broken. That should trigger it. So we say; //see if we have a banner, if we do, add this javaScript, we are done. Save. Let's compile and install. 00:58:37 Go back to our view. Close this and refresh it. Go to More and there is our image.

Changing Of Image - Won't Remove Old One


Now to show you it in action, we are going to change the image. It will not remove the old one, but it will immediately show you the new one once we click save. A different image has been selected from my computer and clicks Save. Go back and there is the new image. That is how you could implement the file field type in JCB. You can see there is some custom scripting needed, I am quickly going to show you a URL where you can go and get this custom script and use it in your own component. Of course, 00:59:44 maybe adapt it, change it. At least use it as a place to start with. Start using the Custom Joomla field type for uploading files. If there are any questions or even suggestions of how to do this easier or faster or safer, leave the comments in the area below the video. I'll be happy to look at it and 01:00:11 make any necessary changes to our snippet or even at the snippet itself, that might be a better place, in the Gits where the URL is, or you can go there and make comments there and we will make pull request and fix it up.