Multiple File Upload styles in a form can be beautified using JS. Related items can be deleted after a selected file is selected, and JavaScript files can be uploaded.
During development, the file upload needs are often involved. Different file uploads vary depending on different business needs.
There are simple single file uploads and multi-file uploads. Because the browser's native File Upload style and function support is not too high, we often beautify the style, complete the functions.
Based on an example, this article makes some simple beautification (in fact, it is not very beautifying) on the upload style of multiple files ..), At the same time, you can select a file, delete the relevant file, and then upload the file.
The article is long. Let's take a look at the illustration:
I. File Upload Basics
1. Upload a single file
The simplest file Upload method is single file upload. enctype = "multipart/form-data" is added to the form label. The form contains an input [type = "file"] item.
<Form name = "form1" method = "post" action = "/abc. php "enctype =" multipart/form-data "> <input type =" text "name =" user "id =" user "placeholder =" Enter nickname "> <input type = "file" name = "userImage" id = "userImage"> <input type = "submit" name = "sub" value = "submit"> </form>
2. Multifile upload
1) similar to single file upload, simple multi-file Upload is actually a few more input [type = "file"] items
<Form name = "form1" method = "post" action = "/abc. php "enctype =" multipart/form-data "> <input type =" text "name =" user "id =" user "placeholder =" Enter nickname "> <input type = "file" name = "userImage1" id = "userImage1"> <input type = "file" name = "userImage2" id = "userImage2"> <input type = "file" name = "userImage3" id = "userImage3"> <input type = "submit" name = "sub" value = "submit"> </form>
2) HTML5 adds a multiple attribute for Form file items. You can set and select multiple files, as shown in figure
<Form name = "form1" method = "post" action = "/abc. php" enctype = "multipart/form-data">
<Input type = "text" name = "user" id = "user" placeholder = "enter a nickname">
<Input type = "file" name = "userImage" id = "userImage" multiple>
<Input type = "submit" name = "sub" value = "submit">
</Form>
Ii. beautification of Form file uploads
After reading the above images, we can see that the style of the native file selection item is the most basic, mainly reflected in three points:
No border, not in combination with other elements with borders
Selecting the file button style is too basic
After multiple files are selected, only the total number is displayed. The selected file name is not displayed.
Based on several issues, you can beautify it as needed
You can add a border style directly at the first point.
Second, you need to add other elements. You can add a button (as needed) to hide the original file box, bind it with JS events, and click the button to simulate the clicking of the file box.
<Input type = "file" name = "userImage" id = "userImage" style = "display: none; "> <input type =" button "id =" "value =" select file "onclick =" document. getElementById ('userimage '). click () ">
The third point is similar to the second point. You must add new elements. After selecting a file, you can use JS to obtain the selected file information and display it in the new element.
It is easy to think about, but the problem is that if the number of selected files is large, the amount of space occupied by new elements is a problem. Several files can be displayed by default, then you can view more information through "view more files ".
The other idea is that there are a lot of files selected at one time, and you have to reselect a file when you want to cancel it. This is too cumbersome, so you need to delete a selected file in real time.
3. Delete selected files
To provide the operations that can be deleted after the selected file is selected, you must provide the relevant entry and script operations. The following describes how to resolve this issue.
1. interface processing
After selecting a file, you can click the delete button to delete the selected file. Because multiple files may occur, an Information Template is required.
<! -- Currently selected file list file information template --> <script type = "text/template" id = "file-temp-item-tpl"> <span class = "file-temp -item "style =" {style }}"> <span class = "file-temp-name" >{{ name }}</span> <span class = "file -temp-btn "> × </span> </script>
If there are more than one selected file, you need to add a drop-down box for assistance to display up to five file information. Then, use the drop-down button to expand the drop-down box (the button style is set by yourself)
Here, the location calculation between the five files is not very in place, mainly this code, you can set it yourself
// Calculate the left and widthleft of each coordinate item = I === 0? 2: 2 + I * (100/fileTempLen); width = 100/fileTempLen-2;
Each item in the drop-down list is also a template.
<! -- View more file Information templates --> <script type = "text/template" id = "file-more-item-tpl"> <li> <span class = "file -item-more-name ">{{ name }}</span> <span class =" file-item-more-btn ">×</span> </li> </script>
The following figure shows the initial HTML structure.
<Form name = "form" id = "form" method = "post" action = "fileTest. php" enctype = "multipart/form-data"> <! -- <Input type = "number" name = "numberTest" value = "100"> --> <input type = "file" name = "fileTest []" id = "fileTest" multiple> <! -- List of currently selected files (up to five files can be displayed) --> <span class = "file-temp"> </span> <! -- View more files --> <ul class = "item-more"> </ul> <input type = "button" class = "btn-success" id = "uploadBtn "value =" upload "> <p class =" upload-tip "> the file is uploaded successfully </p> </form>
The following are all CSS styles:
<link rel="stylesheet" type="text/css" href="bootstrap.min.css"> <style type="text/css"> html { font-family: Arial; } form { margin: 50px auto; width: 400px; } input { width: 300px; padding: 4px; } #uploadBtn { margin-top: -3px; margin-left: 5px; width: 60px; height: 30px; font-weight: bold; font-size: 12px; } #fileTest { display: inline-block; border: 1px solid #ccc; border-radius: 3px; } .file-temp { position: relative; display: none; width: 300px; height: 31px; } .file-temp-item { position: absolute; top: 4px; height: 24px; } .item-more-btn { display: inline-block; position: absolute; top: 18px; right: 0.5%; width: 10px; height: 10px; color: #777; cursor: pointer; } .item-more-btn:hover { border-top-color: #aaa; } .file-temp-name { display: inline-block; overflow: hidden; width: 90%; height: 26px; padding: 2px 15px 2px 5px; border-radius: 2px; background-color: #eaeaf3; text-overflow: ellipsis; white-space: nowrap; } .file-temp-btn { position: absolute; display: inline-block; top: 4px; right: 11%; width: 18px; height: 18px; line-height: 18px; text-align: center; border: 1px solid #ddd; background-color: #ccc; border-radius: 50%; color: #fff; font-size: 18px; cursor: pointer; } .item-more { position: absolute; overflow-y: auto; display: none; padding-left: 0; width: 300px; max-height: 150px; list-style: none; } .item-more li { position: relative; padding: 5px; border: 1px solid #ccc; border-top: none; } .item-more li:hover { background-color: #f5f5f9; } .file-item-more-name { display: inline-block; width: 90%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .file-item-more-btn { position: absolute; display: inline-block; top: 8px; right: 2%; width: 18px; height: 18px; line-height: 18px; text-align: center; border: 1px solid #ddd; background-color: #ddd; border-radius: 50%; color: #fff; font-size: 18px; cursor: pointer; } .file-item-more-btn:hover { background-color: #ccc; } .upload-tip { display: none; margin: 50px auto; text-align: center; font-size: 12px; } </style>
2. Script Processing
Next, we will focus on processing JS scripts.
To get the information of the selected file, you naturally want to use the value attribute, but you can only get one file path (the first one) through the value of the file item, no matter whether there is a multiple
No multiple
<input type="file" onchange="console.log(this.value);">
Multiple
<input type="file" multiple onchange="console.log(this.value);">
Since the information of all selected files cannot be obtained through value, you can only seek other methods.
1) FileList
Obtain information about the selected file. You can also use the FileList object, which is added in HTML5. Each form file item has a file attribute, which stores some information about the selected file.
<input type="file" multiple onchange="console.log(this.files);">
Select two files and view the file information.
The FileList object looks like a class array with the length attribute. Therefore, we should be able to customize the selected file by modifying or deleting related items (note that this cannot be modified, and continue reading)
If I select two files and want to delete the second project and use splice to delete them
<input type="file" multiple onchange="console.log(Array.prototype.splice.call(this.files, 1, 1));">
An error is reported. It can be seen that the length attribute of FileList is read-only, so it can be directly modified to writable and configurable.
Object.defineProperty(FileList.prototype, 'length', {writable: true,configurable: true});
After the configuration, the length can be modified. At first glance, we thought the splice was effective. However, after the output, the content of the FileList object remains unchanged.
After reading some documents, I learned that the browser can set the content of the FileList object to unchangeable for security reasons. You can only set it to null manually, but cannot modify the content.
Therefore, the solution is to add an array, first copy the file content of the FileList object, and then modify the object through this changeable array.
// Store and update the selected file var curFiles = [];... // var files = this. files; if (files & files. length) {// The original FileList object cannot be changed. Therefore, assign curFiles to provide the next modification to Array. prototype. push. apply (curFiles, files );}
If you click Delete, you can directly update the file information array.
Var name = $ (this). prev (). text (); // remove the file curFiles = curFiles. filter (function (file) {return file. name! = Name ;});
In this way, the problem of updating file information is solved, and then the file can be uploaded.
Click Upload. If you call $ form. submit () directly, the information of the uploaded file is still the initial FileList object, which does not meet our custom requirements. Therefore, you need to submit the file using Ajax.
So how can I provide a file object in the background?
2) FormData
HTML5 introduces the new FormData object of the form, which can generate a form object. We can obtain/set the key-value pairs and then submit them to the background.
REFERENCE The FormData usage method of MDN. We can add various types of data and use ajax to submit
Var oMyForm = new FormData (); oMyForm. append ("username", "Groucho"); oMyForm. append ("accountnum", 123456); // The number 123456 is immediately converted to the string "123456" // fileInputElement contains the file oMyForm selected by the user. append ("userfile", fileInputElement. files [0]); var oFileBody = '<a id = "a"> <B id = "B"> hey! </B> </a> '; // The file content contained in the Blob Object var oBlob = new Blob ([oFileBody], {type: "text/xml "}); oMyForm. append ("webmasterfile", oBlob); var oReq = new XMLHttpRequest (); oReq. open ("POST", "http://foo.com/submitform.php"); oReq. send (oMyForm );
You can also use JQ-encapsulated ajax. However, you must set the processData and contentType attributes to false to prevent JQ from parsing the file format randomly.
Var fd = new FormData (document. getElementById ("fileinfo"); // use a form as the initial item fd. append ("CustomField", "This is some extra data"); $. ajax ({url: "stash. php ", type:" POST ", data: fd, processData: false, // tell jQuery not to process the sent data contentType: false // tell jQuery not to set the Content-Type Request Header });
Here are a few notes:
1) The attribute values in FormData accept the information of a single file and cannot be composite objects. May be unclear and can be viewed
var fd = new FormData($('#form')[0]);fd.append('myFileTest', curFiles);$files = $_REQUEST['myFileTest'];var_dump($files);
The data received in PHP is directly converted to a string instead of a file object.
CurFiles is a file object. Should the PHP end use $ _ FILES to receive information? Replace it with $ files =$ _ FILES ['myfiletest'];
If a problem occurs directly, it means that the process cannot be done in this way. You need to split the contents of curFiles one by one, that is, the information of a single file.
var fd = new FormData($('#form')[0]);for (var i = 0, j = curFiles.length; i < j; ++i) {fd.append('myFileTest[]', curFiles[i]);}$files = $_FILES['myFileTest'];var_dump($files);
After the file is successfully received, you can perform operations on the file as needed.
2) When the backend obtains the file information, it is obtained directly through the original $ _ FILES, and other general information is obtained using $ _ REQUEST.
Change to $ files =$ _ REQUEST ['myfiletest']; try it. The problem is that myFileTest cannot be found.
Try adding a normal file and submit it again
var fd = new FormData($('#form')[0]);for (var i = 0, j = curFiles.length; i < j; ++i) {fd.append('myFileTest[]', curFiles[i]);}fd.append('myTest', [1, 2, 3]);$files = $_FILES['myFileTest'];$test = $_REQUEST['myTest'];var_dump($test);var_dump($files);
3) if multiple Multifile upload is required, you need to add the [] number after the file entry, indicating that this is an array of multiple files for backend processing and parsing.
fd.append('myFileTest[]', curFiles[i]);
If [] is not followed, the continuous append will directly overwrite the original one. The last result obtained by the backend is the last append entry.
4) do not directly instantiate a FormData object in JQ's ajax.
The FormData object is generated directly in the data Attribute and will be ignored by JQ. Therefore, no backend information can be obtained.
A simple example of mixed form items:
In form processing, many times we upload files and submit other basic items. Simply add an input project to check whether the processing is successful.
<input type="number" name="numberTest" value="100">
<?php$files = $_FILES['myFileTest'];$test = $_REQUEST['numberTest'];echo json_encode(array('len' => count($files['name']),'num' => $test));?>
The following are all JS scripts:
<Script type = "text/javascript">/*** Add the corresponding file item * @ param {Array} files to the file list element */function addItem (files) {var fileTempItemTpl = require (), fileMoreItemTpl = require ('{file-more-item-tpl'{.html () htmlTemp = [], htmlMoreTemp = [], // The coordinates and spaces of each file in the file list left = 2, width = 100, // obtain the first five files fileTempLen = files. length> 5? 5: files. length; for (var I = 0, j = files. length; I <j; ++ I) {// when I> 4, that is, 6th files start if (I> 4) {htmlMoreTemp. push (fileMoreItemTpl. replace ('{name}', files [I]. name); continue;} // calculate the left and widthleft of each coordinate item = I === 0? 2: 2 + I * (100/fileTempLen); width = 100/fileTempLen-2; htmlTemp. push (fileTempItemTpl. replace ('{style}', 'left: '+ left +' %; width: '+ width +' % ;'). replace ('{name}', files [I]. name);} // specify the content of the relevant element ('.file-temp'0000.html (''+ '<input type =" text "style =" background-color: # fff; "class =" form-control "id =" fileTemp "readonly> '+ htmlTemp. join ('') + (files. length> 5? '<Span class = "item-more-btn" title = "view more" >=</span>': ''{}}('.item-more'}.html (htmlMoreTemp. join ('');} // Save the list of currently selected (updated) files var curFiles = []; // trigger $ ('# filetest') during initial file selection '). change (function () {var $ this = $ (this), $ temp = $ ('. file-temp '), files = this. files; if (files & files. length) {// The original FileList object cannot be changed. Therefore, assign curFiles to provide the next modification to Array. prototype. push. apply (curFiles, files); addItem (curFiles); $ this. hide (); $ temp. Css ('display', 'inline-Block') ;}}); $ (document) // when you cancel a file selection, delete this value from the array object in the file list, and update the list. on ('click ','. file-temp-btn ,. file-item-more-btn ', function () {$ ('. upload-tip '). hide (); var name = $ (this ). prev (). text (); // remove the file curFiles = curFiles. filter (function (file) {return file. name! = Name ;}); // if (curFiles. length <= 5) {$ ('. item-more '). hide ();} // if (! CurFiles. length) {}('{filetest'}.val(''{.show({}}('.file-temp'}.css ('display', 'None');} else {addItem (curFiles);} console. log (curFiles)}) // display the "more files list" drop-down list. on ('click ','. item-more-btn ', function () {$ ('. upload-tip '). hide (); $ ('. item-more '). show ('normal') ;}); // upload operation $ ('# uploadBtn '). click (function () {$ ('. upload-tip '). hide (); // construct the FormData object var fd = new FormData ($ ('# form') [0]); for (var I = 0, j = curFiles. length; I <j; ++ I) {fd. append ('myfiletest [] ', curFiles [I]);} $. ajax ({url: 'filetest. php ', type: 'post', data: fd, processData: false, contentType: false, success: function (rs) {rs = JSON. parse (rs); $ ('. upload-tip '). addClass ('text-success '). removeClass ('text-error '). text (rs. len + 'file uploaded successfully. The value of number is '+ rs. num ). show () ;}, error: function (err) {}}) ;}); </script>
The above section describes how to use JavaScript to create multiple file upload styles in a form. You can delete the selected file. I hope it will be helpful to you. If you have any questions, please leave a message, the editor will reply to you in a timely manner. Thank you very much for your support for the help House website!