Long heard of the breakpoint extension of this thing, the front-end can also be achieved. The implementation of the breakpoint on the front end relies mainly on the new features of the HTML5, so the support on the old browsers is generally not high.
This article through a simple example of the continuation of the breakpoint (front-end file submission + back-end PHP file reception), understand its general implementation process
Let's take a picture for example and look at the last appearance.
First, some knowledge preparation
Breakpoint continues to pass, since there is a break, that should have the process of file segmentation, a section of the biography.
Previous files could not be segmented, but with the introduction of new HTML5 features, similar to ordinary string, array segmentation, we can use the slice method to split the file.
Therefore, the most basic implementation of the breakpoint is: the front-end through the FileList object to obtain the corresponding file, according to the designated partition mode will be a large file segmentation, and then a paragraph to the back end, the back end in order a section of the file to be spliced.
And we need to modify the FileList object to submit, in the previous article, we know some of the points of attention to this submission, because the FileList object can not be directly changed, so can not directly through the form of the. Submit () method upload submission, You need to combine the Formdata object to generate a new data, upload through Ajax operation.
Second, the implementation process
This example implements the basic function of file breakpoint, but the manual "suspend upload" operation has not been successful, can refresh the page in the upload process to simulate the interruption of the upload, experience the "breakpoint continued transmission",
There may be some other minor bugs, but the basic logic is generally the same.
1. Front-End implementation
First select the file, listing the selected file list information, and then you can customize the upload operation
(1) So set the page DOM structure
first.
<!--uploaded form--> <form method= "POST" id= "MyForm" action= "/filetest.php" enctype= "Multipart/form-data" > < Input type= "file" id= "MyFile" multiple> <!--uploaded file list--> <table id= "upload-list" > <thead> <tr > <th width= "35%" > FileName </th> <th width= "15%" > File type </th> <th width= "15%" > File size </th > <th width= "20%" > Upload progress </th> <th width= "15%" > <input type= "button" id= "Upload-all-btn" value= " Upload All "> </th> </tr> </thead> <tbody> </tbody> </table> </form> <!-- The information template for each file in the upload file list--> <script type= "text/template" id= "File-upload-tpl" > <tr> <td>{{filename}} </td> <td>{{fileType}}</td> <td>{{fileSize}}</td> <td class= "Upload-progress" > {{progress}}</td> <td> <input type= "button" class= "Upload-item-btn" Data-name= "{{fileName}}" Data-size= ' {{totalsize}} ' data-state= ' default ' value= ' {{uploadval}} ' > </td> </tr> </script>
Here's a CSS style thrown out
<style type= "Text/css" > Body
{
font-family:arial;}
form {
margin:50px auto;
width:600px; }
input[type= "button"] {
Cursor:pointer}
Table {
display:none;
margin-top:15px;
border:1px solid #ddd;
Border-collapse:collapse;
table th {
color: #666;}
Table TD,
table th {
padding:5px;
border:1px solid #ddd;
Text-align:center;
font-size:14px; }
</style>
(2) Next is the implementation of JS analysis
We can get some information about the file through the FileList object
The size of which is the file sizes, the file partition fragmentation needs to rely on this
The size here is the byte number, so when the interface shows the file size, you can convert
Size of the calculated file = file.size > 1024? file.size/1024 > 1024? File.size/(1024 * 1024) > 1024? (File.size/(1024 * 1024 * 1024)). ToFixed (2) + ' GB ': (File.size/(1024 * 1024)). ToFixed (2) + ' MB ': (file.size/1024). ToFixed (2) + ' KB ': (file.size). toFixed (2) + ' B ';
Select the file to display the file information, replace the data in the stencil
Update file Information list Uploaditem.push (Uploaditemtpl
. Replace (/{{filename}}/g, File.name)
. Replace (' {{fileType}} ', File.type | | File.name.match (/\.\w+$/) + ' file ')
. Replace (' {{fileSize}} ', size)
. Replace (' {{Progress}} ', progress)
. Replace (' {{totalsize}} ', File.size)
. Replace (' {{uploadval}} ', Uploadval)
);
However, when displaying file information, this file may have been uploaded before, in order to continue the transmission of the breakpoint, you need to judge and in the interface to make a prompt.
Check to see if there is data locally (this is done when the local record is already uploaded 100%, it is simply uploading instead of uploading)
Initial through local records, to determine whether the file has been uploaded percent = Window.localStorage.getItem (file.name + ' _p '); If (percent && percent!== ' 100.0 ') {
progress = ' uploaded ' + percent + '% ';
Uploadval = ' Continue uploading ';
}
Displays a list of file information
Click Start Upload, you can upload the corresponding file
When uploading files, you need to fragment the files.
For example, the configuration of each section 1024B, a total of chunks paragraph (used to determine whether the last paragraph), paragraph chunk, the current percentage of the upload percent.
Need to mention is this suspend the upload operation, in fact I have not realized, pause not helpless ing ...
The next step is the staging process
Set the beginning end of the fragment var blobfrom = chunk * eachsize,//Sub Start blobto = (chunk + 1) * eachsize > TotalSize? TotalSize: (chunk + 1) * eachsize,//segmented end percent = (* blobto/totalsize). toFixed (1),//uploaded percentage timeout = 5000,// Timeout period fd = new FormData ($ (' #myForm ') [0]);
Fd.append (' Thefile ', Findthefile (fileName). Slice (Blobfrom, blobto)); The document fd.append (' filename ', filename); FileName fd.append (' totalsize ', totalsize); Total file Size fd.append (' Islastchunk ', islastchunk); Is the last segment Fd.append (' Isfirstupload ', times = = ' 1:0 '); is the first paragraph (first upload)
//upload before the query whether and upload too much film chunk = Window.localStorage.getItem (fileName + ' _chunk ') | | 0;
Chunk = parseint (chunk, 10);
The file should support overlay upload, so if the file and upload is finished, and now upload, you should reset the data to support the overlay (no and then append the BLOB data directly)
If the first upload is the final fragment, that is, the file has been uploaded, then overwrite the upload if (times = =, ' first ' && islastchunk = 1) {Window.localStorage.setItem (filen) Ame + ' _chunk ', 0);
chunk = 0;
Islastchunk = 0;
}
The Times is actually a parameter, because to pass the next fragment after the last fragment is passed, the practice here is to continue invoking the upload in the callback
Next is the real file upload operation, with Ajax upload, because the use of Formdata objects, so don't forget to $.ajax ({} Plus this configuration Processdata:false
Upload a section, through the return of the results to determine whether the upload completed, continue to upload
Success:function (RS) {
rs = json.parse (RS);//Upload success if (rs.status = = 200) {//Record already uploaded percentage window.localStorage.setIte M (fileName + ' _p ', percent); Already uploaded if (chunk = = (chunks-1)) {
$progress. Text (msg[' done '));
$this. Val (' already uploaded '). Prop (' disabled ', true). CSS (' cursor ', ' not-allowed '); if (!$ (' #upload-list '). Find ('. Upload-item-btn:not (:d isabled) '). Length) {
$ (' #upload-all-btn '). Val (' already uploaded '). Prop (' disabled ', true). CSS (' cursor ', ' not-allowed ');
}
else {//record already uploaded fragment Window.localStorage.setItem (FileName + ' _chunk ', ++chunk);
$progress. Text (msg[' in '] + percent + '% '); This setting can be paused, but the dynamic settings will not pause after clicking. if (chunk = =) {//ispaused = 1;//} console.log (ispaused);
if (!ispaused) {
startupload ();
}}} Upload failure, upload failure in a number of cases, specific according to the actual set else if (Rs.status = =) {
$progress. Text (msg[' failed ']);
}
,
Error:function () {
$progress. Text (msg[' failed ']);
To continue the next segment of the upload, the recursive operation, in order to pass the next section of the ground
Cut a picture.
This is the complete JS logic, the code a little bit of comment should not ugly understand it haha
2. Back-end implementation
Here the backend implementation is relatively simple, mainly rely on the file_put_contents, file_get_contents these two methods
To pay attention to, through the Formdata object uploaded file object, in PHP is also through the $_files global object to obtain, and to avoid uploading files in Chinese garbled, use the Iconv
The breakpoint continues to overwrite the supporting file, so if you already have the complete file, delete it
If the file already exists the first time it is uploaded, delete the file and upload the if ($isFirstUpload = = ' 1 ' && file_exists (' upload/'. $fileName) && FileSize (' upload/'. $fileName) = = $totalSize) {
unlink (' upload/'. $fileName);
}
Using the above two methods, the file information is appended, don't forget to add file_append this parameter ~
Continue appending file data if (!file_put_contents (' upload/'. $fileName, file_get_contents ($_files[' thefile '] [' tmp_name ']), File_ APPEND) {
$status = 501
} else {//when the last fragment is uploaded, the detection file is complete (size is consistent) if ($isLastChunk = = ' 1 ') {if (filesize) (' upload/ '. $fileName) = = $totalSize) {
$status = =/
else {
$status = 502;
}} else {
$status =;
}
}
Generally after the transfer will need to check the file, so here is a simple check the file size is consistent.
Depending on the actual requirements of different methods of error handling, here is not much to deal with
The Complete PHP section
<?php header (' Content-type:text/plain; Charset=utf-8 ');
$files = $_files[' thefile '];
$fileName = Iconv (' utf-8 ', ' GBK ', $_request[' fileName '));
$totalSize = $_request[' totalsize '];
$isLastChunk = $_request[' Islastchunk ']; $isFirstUpload = $_request[' isfirstupload ']; if ($_files[' thefile '] [' ERROR '] > 0} {$status = +} else {//Here is the general file upload operation//if (!move_uploaded_file ($_files[' Thef Ile '] [' tmp_name '], ' upload/'. $_files[' thefile ' [' name ']) ' {//$status = 501;//} else {//$status = 200;////The following section is a file breakpoint continuation operation////If the first upload, the file already exists , delete the file to upload if ($isFirstUpload = = ' 1 ' && file_exists (' upload/'. $fileName) && filesize (' upload/'. $ fileName) = = $totalSize) {unlink (' upload/'. $fileName);}//or continue appending file data if (!file_put_contents (' upload/'. $fileName, File _get_contents ($_files[' thefile '] [' tmp_name ']) (File_append)) {$status = 501;} else {//when the last fragment is uploaded, the detection file is complete (size is consistent) if ($ Islastchunk = = ' 1 ') {if (filesize (' upload/'. $fileName) = = $totalSize) {$status = =} else {$status = 502;}}
else {$status = 200;}} echo json_encode (' status ' => $status, ' totalsize ' => filesize (' upload/'. $fileName), ' Islastchunk ' => $i Slastchunk));?>