How to validate the content-type of a file before uploading using JavaScript? I'm not asking the extension validation. I want to validate pdf,plain text and MS word files.
I'm using a django forms.ModelForm to pass file upload widget to html. I couldn't achieve this either on server side. Here is that question,
Django - Uploaded file type validation
Maybe but it won't give you any form of security because an attacker could use other means to upload files thus circumventing your validation.
To check the file type using the extension (which is very insecure since it's dead easy to manipulate it), you can use JavaScript. See this question: How do I Validate the File Type of a File Upload?
[EDIT] After some googling, I found that the input element has an attribute accept which takes a list of mime type patterns. Unfortunately, most browsers ignore it (or only use it to tweak the file selection dialog). See this question: File input 'accept' attribute - is it useful?
[EDIT 2] Right now, it seems that the File API (see "Using files from web applications") is your only way it you really don't want to use file extensions. Each File instance has a type property which contains the mime type.
But this API is work in progress, so it's not available everywhere. And there is no guarantee that you'll get a MIME type (the property can be "").
So I suggest this approach: Try the File API. If it's not available or the type property is empty, use the file extension.
In theory you could use the File API to read the files.
You would then need to write parsers in JavaScript for the file formats you cared about to check if they matched.
Related
How can I get MIME type of a text file with no extension in Node.js? I am using file-type package, but it does not detect file type of text files.
Thanks
Without a helper package, you can't easily tell of which format is a certain text file. There just isn't a place where different file formats say who they are; you would have to use a bunch of regexes, one for each file format.
This question already has answers here:
Use File Content to Determine MIME Type with Node JS
(2 answers)
Closed 2 years ago.
Hey everyone I'm trying to get the file type in Node.js. I have to rename the file before it's uploaded for version control and once the file is written then run some processing on it.
I'm aware that I can check the file type on the client but I still think it would be beneficial to do a server side check as well.
Other solutions have popped the file extension off the file name:
return filename.split('.').pop();
But since I'm renaming this file and a user could simply rename a malicious file to a whitelisted extension I'm looking for a solution that actually determines the file type, specifically CSV.
Can anyone point me in the direction of solving this?
To read the file extension you may use the snippet:
const { extname } = require('path')
console.log(extname('foo.csv')) // .csv
console.log(extname('BAR.CSV')) // .CSV
But since I'm renaming this file and a user could simply rename a malicious file to a whitelisted extension I'm looking for a solution that actually determines the file type, specifically CSV.
Usually, to implement this check, you need to read the magic bytes of the file and act accordingly for a limited set of file types but CSV is not in this list.
CSV is a plain text with a defined format, so you could:
read some line an try to parse them
define that the CSV must have a defined header like id,col1,col2,etc
use some tools that try to guess the mime type of the file (like mime-types )
What I need to do is:
Let user choose txt file from his disc
Get the text from it to let's say a variable
Send it (the variable value) via AJAX
For the first point I want to know if I should use normal input type (like if I would like to send file via POST) <input type="file">
For the second point I need to know how to get the name of the file user selected and then read text from it. Also I'm not good with javascript so I don't really know how long can a string be there (file will have about 15k lines on average)
For the third I need nothing to know if I can have the data stored in a variable or an array.
Thanks in advance.
P.S. I guess javascript is not a fast language, but (depending on the editor) it sometimes opens on my computer the way that I have all the needed data in first 5 or 6 lines. Is it possible to read only first few lines from the file?
It is possible to get what you want using the File API as #dandavis and other commentors have mentioned (and linked), but there are some things to consider about that solution, namely browser support. Bottom line is the File API is currently a working draft of the w3c. And bottom line is even w3c recommended things aren't always fully supported by all browsers.
What solution is "best" for you really boils down to what browser/versions you want to support. If it were my own personal project or for a "modern" site/audience, I would use the File API. But if this is for something that requires maximum browser support (for older browsers), I would not currently recommend using the File API.
So having said all that, here is a suggested solution that does NOT involve using the FIle API.
supply an input type file in a form for the user to specify file. User will have to select the file (javascript cannot do this)
use form.submit() or set the target attribute to submit the form. There is an iframe trick for submitting a form without refreshing the page.
use server-side language of choice to respond with the file info (name, contents, etc.). For example in php you'd access the posted file with $_FILES
then you can use javascript to parse the response. Normally you'd send it as a json encoded response. Then you can do whatever you want with the file info in javascript.
With Chrome and Firefox you can read the contents of a text file like this:
HTML:
<input type="file" id="in-file" />
JavaScript with jQuery:
var fileInput = $('#in-file');
fileInput.change(function(e) {
var reader = new FileReader();
reader.onload = function(e) {
console.log(reader.result);
}
reader.readAsText(fileInput[0].files[0]);
});
IE doesn't support the FileReader object.
I'm using uploadify + s3, and when trying to upload a file that has question marks in it, Uploadify doesn't give me the correct filename. For example, if the file is named #?? (copy).mp4, the fileObj.name value sent to the event handlers is # (basically everything after and including the question mark is removed).
Ignoring the original filename altogether is not an option, because I also need the extension.
If I try to change the scriptData at runtime, the upload will fail for some reason.
Can you help me out with this issue?
The problem exists above uploadify in actionscript's FileReference object.
From what I can tell the FileReference object chops the name at the question mark and only returns the part in front it.
I tried finding some way of getting to the original filesystem file name before it populated FileReference(event.target).name but I have next to no knowledge of actionscript.
I've also thought about renaming on the server but no mime type is set when the file is uploaded due to how `FileReference' handles the filename. I think it throws away the file ext since it's after the question mark.
I looked into hacking the uploadify Javascript to deal with file name validation and sanitization client side or send something to the server so the name can be fixed when the file is processed but by by the time uploadify has access to the name it's been truncated.
you cant change the value of the input type = 'file' in a form because of security reasons.
But is it possible to read the value at all with javascript to then check extensions and validate the form? or will that also be a security breach?
Some examples would ease my pain...
thanks
You can only read the name of the file and it's extension, so eg: 'file.zip'. It won't tell you the path, unless you are using IE.
Here's a simple example:
<input type="file" onblur="alert(this.value)" />
This will give you the filename + extension..
Sure you can read the value. Just read and validate it as you do for every other form element. Have you tried it yourself anyway? This particular question doesn't make me think so. A bit more programming effort from your side is highly appreciated.
You can read the extension of the filename from input.value, sure. But it won't do you any good. You don't know what file extensions are mapped to the various filetypes under the user's operating system, and you don't even know the user's OS uses filename extensions for filetyping. OS X and Linux users are quite likely to submit files with no file extension at all.
There's nothing worse than an idiotic file upload that won't accept your JPEG because it thinks JPEGs have to end in ‘.jpg’.