Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to realize the breakpoint continuation of files by front-end development

2025-02-23 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article introduces the relevant knowledge of "how to achieve breakpoint continuation of files in front-end development". In the operation of actual cases, many people will encounter such a dilemma. Next, let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

I have heard of such things as breakpoint continuation for a long time, and the front end can also be implemented.

The implementation of breakpoint continuation at the front end mainly depends on the new features of HTML5, so generally speaking, the support is not high on old browsers.

In this paper, the general implementation process is understood through a simple example of breakpoint continuation (front-end file submission + back-end PHP file reception).

Let's take the picture as an example to see what it looks like.

First, some knowledge preparation

Breakpoint continuation, since there is a break, then there should be a process of file segmentation, a paragraph of transmission.

Previously, files could not be split, but with the introduction of new features of HTML5, similar to the splitting of ordinary strings and arrays, we can use the slice method to split files.

So the most basic implementation of breakpoint continuation is that the front end obtains the corresponding file through the FileList object, segments the large file according to the specified segmentation method, and then passes it to the back end one by one, and then splices the files sequentially.

We need to modify the FileList object and then submit it. We know some points for this submission in the previous article. Because the FileList object cannot be changed directly, we cannot upload the submission directly through the .submit () method of the form. We need to combine the FormData object to generate a new data and upload it through Ajax.

Second, the process of realization

This example realizes the basic functions of file breakpoint resume, but the manual "pause upload" operation has not been achieved successfully. You can refresh the page during the upload process to simulate the interruption of upload and experience "breakpoint resume",

There may be some other small bug, but the basic logic is something like that.

1. Front-end implementation

First select the file, list the selected file list information, and then you can customize the upload operation.

(1) so set up the DOM structure of the page first

File name file type file size upload progress

Throw out the CSS style here as well.

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;}

(2) next is the implementation parsing of JS.

We can get some information about the file through the FileList object.

The size is the size of the file. The fragmentation of the file depends on this.

The size here is the number of bytes, so when the file size is displayed in the interface, you can convert it like this

/ / calculate the file size size = 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'

Display the information of the file after selecting the file, and replace the data in the template

/ / update the file information list uploadItem.push (uploadItemTpl. Replace (/ {fileName}} / g, file.name). Replace ('{fileType}}', file.type | | file.name.match (/\.\ file /) + 'file'). Replace ('{fileSize}}', size). Replace ('{progress}', progress). Replace ('{totalSize}}' File.size) .replace ('{uploadVal}}', uploadVal))

However, when displaying the file information, the file may have been uploaded before. in order to resume the upload at the breakpoint, you need to judge and make a prompt on the interface.

Query locally to see if the corresponding data is available (the practice here is that when the local record is 100% uploaded, it is directly re-uploaded instead of continuing to upload)

/ / initially use local records to determine whether the file has ever been uploaded percent = window.localStorage.getItem (file.name +'_ p'); if (percent & & percent! = = '100.0') {progress =' uploaded'+ percent +'%'; uploadVal = 'continue uploading';}

Shows a list of file information

Click start upload, you can upload the corresponding file

When uploading a file, you need to segment the file.

For example, each segment 1024B configured here, a total of chunks segments (used to determine whether it is the last segment), chunk segment, the current percentage of uploaded percent, etc.

Need to mention is this pause upload operation, in fact, I have not achieved, can not pause but ing …

The next step is the segmented process.

/ / set the beginning and end of the part var blobFrom = chunk * eachSize, / / start the part blobTo = (chunk + 1) * eachSize > totalSize? TotalSize: (chunk + 1) * eachSize, / / end of segment percent = (100* blobTo / totalSize) .tofixed (1), / / percentage uploaded timeout = 5000, / / timeout fd = new FormData ($('# myForm') [0]); fd.append ('theFile', findTheFile (fileName) .slice (blobFrom, blobTo)); / / segmented file fd.append (' fileName', fileName) / / File name fd.append ('totalSize', totalSize); / / Total file size fd.append (' isLastChunk', isLastChunk); / / whether it is the last fd.append ('isFirstUpload', times =' first'? 1: 0); / / whether it is a * segment (* upload) / / query whether and upload excessive film chunk = window.localStorage.getItem (fileName +'_ chunk') before upload | | 0 Chunk = parseInt (chunk, 10)

Files should support overlay upload, so if the file has been uploaded and uploaded again now, the data should be reset to support overwriting (no, then the blob data will be appended directly)

/ / if the * upload is the final part, that is, the file has been uploaded, then re-overwrite the upload if (times = = 'first' & & isLastChunk = 1) {window.localStorage.setItem (fileName +' _ chunk', 0); chunk = 0; isLastChunk = 0;}

This times is actually a parameter, because the next segment will be passed after the previous segment is passed, so the approach here is to continue to call the upload operation in the callback.

Next is the real file upload operation, uploading with Ajax, because the FormData object is used, so don't forget to add this configuration processData: false in $.ajax ({})

Upload a segment, and judge whether the upload is completed or continue by the returned result.

Success: function (rs) {rs = JSON.parse (rs); / / successfully uploaded if (rs.status = 200) {/ / record the percentage of uploaded window.localStorage.setItem (fileName +'_ packs, percent); / / uploaded if (chunk = (chunks-1)) {$progress.text (msg ['done']) $this.val ('uploaded'). Prop ('disabled', true) .css (' cursor', 'not-allowed') If (! $('# upload-list') .find ('.upload-item-btn:not (: disabled)') .length) {$('# upload-all-btn') .val ('uploaded') .prop ('disabled', true) .css (' cursor', 'not-allowed') }} else {/ / record the uploaded multipart window.localStorage.setItem (fileName +'_ chunk', + + chunk); $progress.text (msg ['in'] + percent +'%'); / / this setting can be paused, but the dynamic setting cannot be paused after clicking.. / / if (chunk = = 10) {/ / isPaused = 1; / /} console.log (isPaused); if (! isPaused) {startUpload () } / / upload failed. There are many cases of upload failure. Set else if (rs.status = 500) {$progress.text (msg ['failed']);}}, error: function () {$progress.text (msg [' failed']);}

When the upload of the next segment is continued, a recursive operation is performed, and the next segment is passed sequentially.

Take a screenshot..

This is the complete JS logic, the code is a little annotated, it should not be difficult to understand,

/ / all upload operations $_ (document) .on ('click',' # upload-all-btn', function () {/ / No file if (! $('# myFile') .val ()) {$('# myFile') .focus () } / / simulate clicking on other uploadable files else {$('# upload-list .upload-item-btn') .each (function () {$(this). Click ();});}}) / / Select file-display file information $('# myFile') .change (function (e) {var file, uploadItem = [], uploadItemTpl = $('# file-upload-tpl') .html (), size, percent, progress = 'not uploaded', uploadVal = 'start upload'; for (var I = 0, j = upload I)

< j; ++i) { file = this.files[i]; percent = undefined; progress = '未上传'; uploadVal = '开始上传'; // 计算文件大小 size = 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' / / initially use local records to determine whether the file has ever been uploaded percent = window.localStorage.getItem (file.name +'_ p'); if (percent & & percent! = = '100.0') {progress =' uploaded'+ percent +'%'; uploadVal = 'continue uploading' } / / Update file information list uploadItem.push (uploadItemTpl .replace (/ {fileName}} / g, file.name) .replace ('{{fileType}}', file.type | | file.name.match (/\.\ file /) + 'file') .replace ('{{fileSize}}') Size) .replace ('{progress}}', progress). Replace ('{totalSize}}', file.size). Replace ('{uploadVal}}', uploadVal)) } $('# upload-list'). Children ('tbody') .html (uploadItem.join ('')) .end () .show ();}) / * * when uploading a file, extract the corresponding matching file item * @ param {String} fileName needs to match the file name * @ return {FileList} matching file project * / function findTheFile (fileName) {var files = $('# myFile') [0] .files, theFile; for (var I = 0, j = files.length; I)

< j; ++i) { if (files[i].name === fileName) { theFile = files[i]; break; } } return theFile ? theFile : []; } // 上传文件 $_(document).on('click', '.upload-item-btn', function () { var $this = $(this), state = $this.attr('data-state'), msg = { done: '上传成功', failed: '上传失败', in : '上传中...', paused: '暂停中...' }, fileName = $this.attr('data-name'), $progress = $this.closest('tr').find('.upload-progress'), eachSize = 1024, totalSize = $this.attr('data-size'), chunks = Math.ceil(totalSize / eachSize), percent, chunk, // 暂停上传操作 isPaused = 0; // 进行暂停上传操作 // 未实现,这里通过动态的设置isPaused值并不能阻止下方ajax请求的调用 if (state === 'uploading') { $this.val('继续上传').attr('data-state', 'paused'); $progress.text(msg['paused'] + percent + '%'); isPaused = 1; console.log('暂停:', isPaused); } // 进行开始/继续上传操作 else if (state === 'paused' || state === 'default') { $this.val('暂停上传').attr('data-state', 'uploading'); isPaused = 0; } // ***次点击上传 startUpload('first'); // 上传操作 times: 第几次 function startUpload(times) { // 上传之前查询是否以及上传过分片 chunk = window.localStorage.getItem(fileName + '_chunk') || 0; chunk = parseInt(chunk, 10); // 判断是否为末分片 var isLastChunk = (chunk == (chunks - 1) ? 1 : 0); // 如果***次上传就为末分片,即文件已经上传完成,则重新覆盖上传 if (times === 'first' && isLastChunk === 1) { window.localStorage.setItem(fileName + '_chunk', 0); chunk = 0; isLastChunk = 0; } // 设置分片的开始结尾 var blobFrom = chunk * eachSize, // 分段开始 blobTo = (chunk + 1) * eachSize >

TotalSize? TotalSize: (chunk + 1) * eachSize, / / end of segment percent = (100 * blobTo / totalSize) .tofixed (1), / / percentage uploaded timeout = 5000, / / timeout fd = new FormData ($('# myForm') [0]); fd.append ('theFile', findTheFile (fileName) .slice (blobFrom, blobTo)) / / the segmented file fd.append ('fileName', fileName); / / the file name fd.append (' totalSize', totalSize); / / the total file size fd.append ('isLastChunk', isLastChunk); / / whether it is the last segment fd.append (' isFirstUpload', times = = 'first'? 1: 0) / / whether it is a * segment (* uploads) / / upload $.ajax ({type: 'post', url:' / fileTest.php', data: fd, processData: false, contentType: false, timeout: timeout Success: function (rs) {rs = JSON.parse (rs) / / successfully uploaded if (rs.status = 200) {/ / record the percentage of uploaded window.localStorage.setItem (fileName +'_ packs, percent) / / uploaded if (chunk = = (chunks-1)) {$progress.text (msg ['done']); $this.val (' uploaded') .prop ('disabled', true) .css (' cursor', 'not-allowed') If (! $('# upload-list') .find ('.upload-item-btn:not (: disabled)') .length) {$('# upload-all-btn') .val ('uploaded') .prop ('disabled', true) .css (' cursor', 'not-allowed') }} else {/ / record the uploaded multipart window.localStorage.setItem (fileName +'_ chunk', + + chunk); $progress.text (msg ['in'] + percent +'%') / / this setting can be paused, but the dynamic setting can not be paused after clicking. / / if (chunk = = 10) {/ / isPaused = 1; / /} console.log (isPaused); if (! isPaused) {startUpload () } / / upload failed. There are many cases of upload failure. Set else if (rs.status = 500) {$progress.text (msg ['failed']) according to the actual situation. }, error: function () {$progress.text (msg ['failed']);});}})

two。 Back-end implementation

The back-end implementation here is relatively simple, mainly relying on file_put_contents and file_get_contents.

Note that the file object uploaded through the FormData object is also obtained through the $_ FILES global object in PHP, and to avoid garbled code in the uploaded file, use iconv.

Breakpoint continuation supports the overwriting of files, so if a complete file already exists, delete it

/ / if the file already exists at the time of * uploads, delete the file and upload it again if ($isFirstUpload = ='1' & & file_exists ('upload/'.$fileName) & & filesize (' upload/'.$fileName) = = $totalSize) {unlink ('upload/'.$fileName);}

Use the above two methods to append the file information, and don't forget to add the parameter FILE_APPEND ~

/ / continue appending file data if (! file_put_contents ('upload/'.$fileName, file_get_contents ($_ FILES [' theFile'] ['tmp_name']), FILE_APPEND)) {$status = 501 } else {/ / check whether the file is complete (the size is the same) if ($isLastChunk ='1') {if (filesize ('upload/'.$fileName) = = $totalSize) {$status = 200;} else {$status = 502;}} else {$status = 200;}

Generally speaking, it is necessary to check the file after transmission, so here we simply verify whether the file size is the same.

There are different error handling methods according to the actual requirements, so let's not deal with them here.

Complete PHP section

This is the end of the content of "how to achieve breakpoint continuation of files in front-end development". Thank you for your reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report