Getting value from <file> gives C:\fakepath\filename, even in Linux - html

I'm getting some very strange behaviour from a file input element in both Chrome and Opera (possibly more, haven't tested).
I have the following HTML:
<div id="profileImgContainer" class="formFile">
<label>Profile Picture</label><div>
<input type="text" id="profileImgText"><input type="button" value="Choose File" id="profileImgButton">
</div>
<input type="file" id="profileImg" name="profileImg">
</div>
And the following jQuery to get the file input's value and put it in the (visible) textbox. The actual file input is hidden.
$(".formFile input[type='file']").live('change', function()
{
$(this).parents(".formFile").find("input[type='text']").val($(this).val());
});
I've made a JSFiddle for you try out. In Firefox, the text box happily takes the filename (don't care about the path) of the file element. In Chrome and Opera, however, when a file is selected the file path in the visible text box changes to C:\fakepath\[filename] where [filename] is the name of the file chosen. This path is obviously fake but what I want to know is why it's changed to it, and whether the file in the hidden upload element will still upload fine. I'm guessing it's a security feature, but I may be wrong.

This is one attempt to mitigate the security issues you get from allowing arbitrary foreign code to run in your browser: The script (which we assume could come from a malicious attacker) does not get to see (and possibly communicate back via AJAX) information about your local files.
Imagine what could happen if a script could just freely set file uploads and submit forms.
This behaviour concerning file upload controls and scripting is mandated by some sort of standard (I believe part of the DOM specification) for this very reason.

I just want to add a new answer for people facing this issue nowadays. Similar to one of the comments, it's better to use the input element itself. For example:
document.getElementById('file-input').files[0].path
This worked for me.
Similar solution for React:
const inpRef = useRef(null)
return (
<input type="file" onChange={() => {
const filePath = inpRef.current.files[0].path
// You can use more properties by looking at the files object
}} />
)

Related

Typing text in Blazor input fields with Cypress doesn't work

I have a simple web form built with Blazor, which I'm trying to test with Cypress. When I try to type text in a text field, the text is first inputted correctly, but after about a second it disappears from the screen. Similarly, if I select a value from a drop-down list, the correct value flashes on the screen and then disappears. Test passes and there are no errors or warnings in the console.
If I input text or do some other changes myself in the browser, everything works correctly. I can also correctly input text myself in the Cypress browser. The problem only occurs when Cypress is running the test.
This is a simplified version of my form in the .razor file, which can reproduce the problem. TempTableMapping is a simple object, which I use for binding the values.
<EditForm Context="formContext" Model="tempTableMapping">
<div class="modal-body">
<div class="form-label-and-field">
<label for="MappingName">Mapping name: </label>
<InputText id="MappingName" class="form-control" #bind-Value="tempTableMapping.MappingName"></InputText>
</div>
</div>
</EditForm>
The Cypress code I use:
describe('My Test', function () {
it('Type mapping name', function () {
cy.visit('https://localhost:44374/mapping')
cy.get('#MappingName').type("mapping_name")
})
})
I think the problem might be related to some Javascript things that Blazor is doing in the background, but I don't know Blazor well enough to debug it further.
I have read this article (https://remibou.github.io/Test-a-Blazor-App-with-Cypress/) so it should be possible to use Cypress with Blazor. I also tried the polyfill-fix mentioned in the article, but it didn't help in this and isn't probably relevant to this issue. I also noticed the following issue (https://github.com/cypress-io/cypress/issues/4635), which might be related to this issue.
I am using Cypress version 3.7.0.
As a workaround, I noticed that Selenium Webdriver manages to use the Blazor input fields correctly

HTML Filepicker without sending file itself - only filepath [duplicate]

How can I create a directory chooser in html page.
If I use input file element I can select file only, but I need to select directory instead.
I need to do this beacause the user should select a right path inside his computer.
Any solutions ?
Try this, I think it will work for you:
<input type="file" webkitdirectory directory multiple/>
You can find the demo of this at https://plus.google.com/+AddyOsmani/posts/Dk5UhZ6zfF3 ,
and if you need further information you can find it
here.
Can't be done in pure HTML/JavaScript for security reasons.
Selecting a file for upload is the best you can do, and even then you won't get its full original path in modern browsers.
You may be able to put something together using Java or Flash (e.g. using SWFUpload as a basis), but it's a lot of work and brings additional compatibility issues.
Another thought would be opening an iframe showing the user's C: drive (or whatever) but even if that's possible nowadays (could be blocked for security reasons, haven't tried in a long time) it will be impossible for your web site to communicate with the iframe (again for security reasons).
What do you need this for?
As of 2022 there is now a directory picker API:
https://developer.mozilla.org/en-US/docs/Web/API/Window/showDirectoryPicker
async function getDir() {
const dirHandle = await window.showDirectoryPicker();
// run code for dirHandle
}
In case if you are the server and the user (e.g. you are creating an app which works via browser and you need to choose a folder) then try to call JFileChooser from the server when some button is clicked in the browser
JFileChooser chooser = new JFileChooser();
chooser.setCurrentDirectory(new java.io.File("."));
chooser.setDialogTitle("select folder");
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
chooser.setAcceptAllFileFilterUsed(false);
This code snipped is from here
This is my solution. It is the same as the above answers but you should notice that webkitdirectory = "true".
<input id="design" type="file" webkitdirectory = "true" directory/>
I did a work around. I had a hidden textbox to hold the value. Then, on form_onsubmit,
I copied the path value, less the file name to the hidden folder. Then, set the fileInput box to "". That way, no file is uploaded.
I don't recall the event of the fileUpload control. Maybe onchange. It's been a while. If there's a value, I parse off the file name and put the folder back to the box. Of, course you'd validate that the file as a valid file.
This would give you the clients workstation folder.
However, if you want to reflect server paths, that requires a whole different coding approach.
This isn't provided by HTML because of the security risk. <input type='file' /> is closest, but not what you are looking for.
If you're still using IE11 on Windows 10, you may try this example that uses an ActiveX control to achieve what you want.
Again if the OS is Windows, you can use VB scripts to access the core control files to browse for a folder.
If you do not have too many folders then I suggest you use if statements to choose an upload folder depending on the user input details.
E.g.
String user= request.getParameter("username");
if (user=="Alfred"){
//Path A;
}
if (user=="other"){
//Path B;
}

Limit file format when using <input type="file">?

I'd like to restrict the type of file that can be chosen from the native OS file chooser when the user clicks the Browse button in the <input type="file"> element in HTML. I have a feeling it's impossible, but I'd like to know if there is a solution. I'd like to keep solely to HTML and JavaScript; no Flash please.
Strictly speaking, the answer is no. A developer cannot prevent a user from uploading files of any type or extension using front-end validation (HTML/JavaScript).But still, the accept attribute of <input type = "file"> can help to provide a filter in the file select dialog box provided by the user's browser/OS. For example,
<!-- (IE 10+, Edge (EdgeHTML), Edge (Chromium), Chrome, Firefox 42+) -->
<input type="file" accept=".xls,.xlsx" />
should provide a way to filter out files other than .xls or .xlsx. Although the MDN page for input element always said that it supports this, to my surprise, this didn't work for me in Firefox until version 42. This works in IE 10+, Edge, and Chrome.
So, for supporting Firefox older than 42 along with IE 10+, Edge, Chrome, and Opera, I guess it's better to use comma-separated list of MIME-types:
<!-- (IE 10+, Edge (EdgeHTML), Edge (Chromium), Chrome, Firefox) -->
<input type="file"
accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel" />
[Edge (EdgeHTML) behavior: The file type filter dropdown shows the file types mentioned here, but is not the default in the dropdown. The default filter is All files (*).]
You can also use asterisks in MIME-types. For example:
<input type="file" accept="image/*" /> <!-- all image types -->
<input type="file" accept="audio/*" /> <!-- all audio types -->
<input type="file" accept="video/*" /> <!-- all video types -->
W3C recommends authors to specify both MIME-types and their corresponding extensions in the accept attribute. So, the best approach is:
<!-- Right approach: Use both file extensions and their corresponding MIME-types. -->
<!-- (IE 10+, Edge (EdgeHTML), Edge (Chromium), Chrome, Firefox) -->
<input type="file"
accept=".xls,.xlsx, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel" />
JSFiddle of the same: here.
Reference: List of MIME-types
IMPORTANT: Using the accept attribute only provides a way of filtering in the files of types that are of interest. Browsers still allow users to choose files of any type. Additional (client-side) checks should be done (using JavaScript, one way would be this), and definitely file types MUST be verified on the server, using a combination of MIME-type using both the file extension and its binary signature (ASP.NET, PHP, Ruby, Java). You might also want to refer to these tables for file types and their magic numbers, to perform a more robust server-side verification.
Here are three good reads on file-uploads and security.
EDIT: Maybe file type verification using its binary signature can also be done on client side using JavaScript (rather than just by looking at the extension) using HTML5 File API, but still, the file must be verified on the server, because a malicious user will still be able to upload files by making a custom HTTP request.
There is the accept attribute for the input tag. However, it is not reliable in any way.
Browsers most likely treat it as a "suggestion", meaning the user will, depending on the file manager as well, have a pre-selection that only displays the desired types. They can still choose "all files" and upload any file they want.
For example:
<form>
<input type="file" name="pic" id="pic" accept="image/gif, image/jpeg" />
</form>
Read more in the HTML5 spec
Keep in mind that it is only to be used as a "help" for the user to find the right files.
Every user can send any request he/she wants to your server.
You always have to validated everything server-side.
So the answer is: no you cannot restrict, but you can set a pre-selection but you cannot rely on it.
Alternatively or additionally you can do something similar by checking the filename (value of the input field) with JavaScript, but this is nonsense because it provides no protection and also does not ease the selection for the user. It only potentially tricks a webmaster into thinking he/she is protected and opens a security hole. It can be a pain in the ass for users that have alternative file extensions (for example jpeg instead of jpg), uppercase, or no file extensions whatsoever (as is common on Linux systems).
You can use the change event to monitor what the user selects and notify them at that point that the file is not acceptable. It does not limit the actual list of files displayed, but it is the closest you can do client-side, besides the poorly supported accept attribute.
var file = document.getElementById('someId');
file.onchange = function(e) {
var ext = this.value.match(/\.([^\.]+)$/)[1];
switch (ext) {
case 'jpg':
case 'bmp':
case 'png':
case 'tif':
alert('Allowed');
break;
default:
alert('Not allowed');
this.value = '';
}
};
<input type="file" id="someId" />
JSFiddle
Yes, you are right. It's impossible with HTML. User will be able to pick whatever file he/she wants.
You could write a piece of JavaScript code to avoid submitting a file based on its extension. But keep in mind that this by no means will prevent a malicious user to submit any file he/she really wants to.
Something like:
function beforeSubmit()
{
var fname = document.getElementById("ifile").value;
// check if fname has the desired extension
if (fname hasDesiredExtension) {
return true;
} else {
return false;
}
}
HTML code:
<form method="post" onsubmit="return beforeSubmit();">
<input type="file" id="ifile" name="ifile"/>
</form>
Technically you can specify the accept attribute (alternative in html5) on the input element, but it's not properly supported.
You can use the "accept" attribute as a filter in the file select box.
Using "accept" help you filter input files based on their "suffix" or their "MIME type"
1.Filter based on suffix:
Here "accept" attribute just allow to select files with .jpeg extension.
<input type="file" accept=".jpeg" />
2.Filter based on "file type"
Here the "accept" attribute just allows you to select a file with "image/jpeg" type.
<input type="file" accept="image/jpeg" />
Important: We can change or delete the extension of a file, without changing the meme type. For example it is possible to have a file without extension, but the type of this file can be "image/jpeg". So this file can not pass the accept=".jpeg" filter. but it can pass accept="image/jpeg".
3.We can use * to select all kinds of file types. For example below code allows to select all kinds of images. for example "image/png" or "image/jpeg" or ... . All of them are allowed.
<input type="file" accept="image/*" />
4.We can use cama ( , ) as an "or operator" in the select attribute. For example to allow all kind of images or pdf files we can use this code:
<input type="file" accept="image/* , application/pdf" />
Use input tag with accept attribute
<input type="file" name="my-image" id="image" accept="image/gif, image/jpeg, image/png" />
Click here for the latest browser compatibility table
Live demo here
To select only image files, you can use this accept="image/*"
<input type="file" name="my-image" id="image" accept="image/*" />
Live demo here
Only gif, jpg and png will be shown, screen grab from Chrome version 44
I know this is a bit late.
function Validatebodypanelbumper(theForm)
{
var regexp;
var extension = theForm.FileUpload.value.substr(theForm.FileUpload1.value.lastIndexOf('.'));
if ((extension.toLowerCase() != ".gif") &&
(extension.toLowerCase() != ".jpg") &&
(extension != ""))
{
alert("The \"FileUpload\" field contains an unapproved filename.");
theForm.FileUpload1.focus();
return false;
}
return true;
}
You could actually do it with javascript but remember js is client side, so you would actually be "warning users" what type of files they can upload, if you want to AVOID (restrict or limit as you said) certain type of files you MUST do it server side.
Look at this basic tut if you would like to get started with server side validation. For the whole tutorial visit this page.
Good luck!
As mentioned in previous answers we cannot restrict user to select files for only given file formats. But it's really handy to use the accept tag on file attribute in html.
As for validation, we have to do it at the server side. We can also do it at client side in js but its not a foolproof solution. We must validate at server side.
For these requirements I really prefer struts2 Java web application development framework. With its built-in file upload feature, uploading files to struts2 based web apps is a piece of cake. Just mention the file formats that we would like to accept in our application and all the rest is taken care of by the core of framework itself. You can check it out at struts official site.
I may suggest following:
If you have to make user select any of image files by default, the use accept="image/*"
<input type="file" accept="image/*" />
if you want to restrict to specific image types then use accept="image/bmp, image/jpeg, image/png"
<input type="file" accept="image/bmp, image/jpeg, image/png" />
if you want to restrict to specific types then use accept=".bmp, .doc, .pdf"
<input type="file" accept=".bmp, .doc, .pdf" />
You cannot restrict user to change file filer to all files, so always validate file type in script and server
Building on the previous answers of using the accept attribute, you can accomplish this using the File API. This also gives you access to the file contents should you use FileReader to do some local parsing or data handling.
First create an input element, here you could apply the file type to the accept attribute but for the example it will allow you to select all file types.
<input type="file" name="upload" accept="*" multiple>
Next we need to listen to the 'change' event on the input element.
var upload = document.querySelector('input[type="file"]');
upload.addEventListener('change', function() {});
Inside the function you'll be able to access the files object of the input.
var files = this.files
We can't just iterate over the object since it isn't an array, however we can use the item() function to access our File object from the list.
for (var i = 0; i < files.length; i++) {
var file = files.item(i);
}
Now that we have our File object, we can access its name and type properties and do our file check here. In this case I'm checking to see if it's a .txt file and printing a message if it isn't. You can check the name against a regex pattern for the file type or check the type against its MIME type.
if (!file.name.match(/.txt$/i) || file.type != 'text/plain') {
console.log(file.name + ' is not a .txt file.');
}
var upload = document.querySelector('input[type="file"]');
upload.addEventListener('change', function() {
var files = this.files;
for (var i = 0; i < files.length; i++) {
var file = files.item(i);
if (!file.name.match(/.txt$/i) || file.type != 'text/plain') {
console.log(file.name + ' is not a .txt file.');
}
}
});
<input type="file" name="upload" accept="*" multiple>
File API is very well supported for modern browsers. By combining this with the accept attribute you can easily filter what the local user can select in an upload and provide useful feedback. If you are uploading the file, you should still check and validate the file type on your backend.

Make sure <a href="local file"> is opened outside of browser

For an Intranet web application (document management), I want to show a list of files associated with a certain customer. The resulting HTML is like this:
somefile.docx
somefile.pdf
yetanotherfile.txt
This works fine. Unfortunetly, when clicking on a text file (or image file), Internet Explorer (and I guess most other browsers as well) insist on showing it in the browser instead of opening the file with the associated application (e.g. Notepad). In our case, this is undesired behavior, since it does not allow the user to edit the file.
Is there some workaround to this behavior (e.g. something like <a href="file:///..." open="external">)? I'm aware that this is a browser-specific thing, and an IE-only solution would be fine (it's an Intranet application after all).
Do you WANT people to just mess around with things lying on your server? That reeks of lack of security to me...
I'd recommend letting the user check it out locally and using a database or similar to allow people to check in new drafts. Said drafts should be verified and validated somehow before they are actually written to the server's filesystem.
I just tested this and it seems to work (IE6, not in FF or Chrome):
<HTML>
<script language="JavaScript">
function startWord(strFile)
{
var myApp = new ActiveXObject("Word.Application");
if (myApp != null)
{
myApp.Visible = true;
myApp.Documents.Open(strFile);
}
}
</script>
test.doc.
Found it here.

Directory Chooser in HTML page

How can I create a directory chooser in html page.
If I use input file element I can select file only, but I need to select directory instead.
I need to do this beacause the user should select a right path inside his computer.
Any solutions ?
Try this, I think it will work for you:
<input type="file" webkitdirectory directory multiple/>
You can find the demo of this at https://plus.google.com/+AddyOsmani/posts/Dk5UhZ6zfF3 ,
and if you need further information you can find it
here.
Can't be done in pure HTML/JavaScript for security reasons.
Selecting a file for upload is the best you can do, and even then you won't get its full original path in modern browsers.
You may be able to put something together using Java or Flash (e.g. using SWFUpload as a basis), but it's a lot of work and brings additional compatibility issues.
Another thought would be opening an iframe showing the user's C: drive (or whatever) but even if that's possible nowadays (could be blocked for security reasons, haven't tried in a long time) it will be impossible for your web site to communicate with the iframe (again for security reasons).
What do you need this for?
As of 2022 there is now a directory picker API:
https://developer.mozilla.org/en-US/docs/Web/API/Window/showDirectoryPicker
async function getDir() {
const dirHandle = await window.showDirectoryPicker();
// run code for dirHandle
}
In case if you are the server and the user (e.g. you are creating an app which works via browser and you need to choose a folder) then try to call JFileChooser from the server when some button is clicked in the browser
JFileChooser chooser = new JFileChooser();
chooser.setCurrentDirectory(new java.io.File("."));
chooser.setDialogTitle("select folder");
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
chooser.setAcceptAllFileFilterUsed(false);
This code snipped is from here
This is my solution. It is the same as the above answers but you should notice that webkitdirectory = "true".
<input id="design" type="file" webkitdirectory = "true" directory/>
I did a work around. I had a hidden textbox to hold the value. Then, on form_onsubmit,
I copied the path value, less the file name to the hidden folder. Then, set the fileInput box to "". That way, no file is uploaded.
I don't recall the event of the fileUpload control. Maybe onchange. It's been a while. If there's a value, I parse off the file name and put the folder back to the box. Of, course you'd validate that the file as a valid file.
This would give you the clients workstation folder.
However, if you want to reflect server paths, that requires a whole different coding approach.
This isn't provided by HTML because of the security risk. <input type='file' /> is closest, but not what you are looking for.
If you're still using IE11 on Windows 10, you may try this example that uses an ActiveX control to achieve what you want.
Again if the OS is Windows, you can use VB scripts to access the core control files to browse for a folder.
If you do not have too many folders then I suggest you use if statements to choose an upload folder depending on the user input details.
E.g.
String user= request.getParameter("username");
if (user=="Alfred"){
//Path A;
}
if (user=="other"){
//Path B;
}