


Le front-end implémente le téléchargement de reprise de point d'arrêt des fichiers (soumission de fichiers front-end, réception de fichiers PHP back-end)
Dec 26, 2016 pm 02:01 PMJ'entends parler du téléchargement de CV avec point d'arrêt depuis longtemps, et le front-end peut également l'implémenter. L'implémentation du téléchargement de CV avec point d'arrêt sur le front-end repose principalement sur les nouvelles fonctionnalités de HTML5, donc d'une manière générale, la prise en charge sur les navigateurs plus anciens n'est pas élevée.
Cet article utilise un exemple simple de reprise de point d'arrêt (soumission de fichier front-end et réception de fichier PHP back-end) pour comprendre son processus général de mise en ?uvre
Prenons d'abord la photo comme exemple pour voir à quoi ?a ressemble au final
1. Quelques préparations de connaissances
Reprendre le téléchargement aux points d'arrêt depuis là. s'il y a une rupture, il devrait y avoir une division des fichiers. Le processus est transmis pièce par pièce.
Dans le passé, les fichiers ne pouvaient pas être divisés, mais avec l'introduction de nouvelles fonctionnalités de HTML5, similaires au fractionnement de cha?nes et de tableaux ordinaires, nous pouvons utiliser la méthode slice pour diviser des fichiers.
Ainsi, l'implémentation la plus basique de la reprise du point d'arrêt est la suivante?: le frontal obtient le fichier correspondant via l'objet FileList, divise le gros fichier en segments selon la méthode de division spécifiée, puis le transmet au back-end. par pièce. Ensuite, assemblez les fichiers pièce par pièce dans l'ordre.
Nous devons modifier l'objet FileList puis le soumettre. Dans l'article précédent, nous avons appris quelques points à noter sur ce type de soumission. Parce que l'objet FileList ne peut pas être modifié directement, il ne peut pas être directement transmis. la méthode .submit() du formulaire. Pour télécharger et soumettre, vous devez combiner l'objet FormData pour générer de nouvelles données et effectuer l'opération de téléchargement via Ajax.
2. Processus d'implémentation
Cet exemple implémente la fonction de base de reprise du téléchargement de fichiers aux points d'arrêt. Cependant, l'opération manuelle de ??pause du téléchargement?? n'a pas réussi. processus de téléchargement. Simulez l'interruption du téléchargement et expérimentez un "téléchargement qui peut reprendre".
Il peut y avoir d'autres petits bugs, mais la logique de base est à peu près la même.
1. Implémentation frontale
Sélectionnez d'abord le fichier, répertoriez les informations de la liste des fichiers sélectionnés, puis personnalisez l'opération de téléchargement
(1) Configurez donc la page première structure DOM
<!-- 上傳的表單 --> <form method="post" id="myForm" action="/fileTest.php" enctype="multipart/form-data"> <input type="file" id="myFile" multiple> <!-- 上傳的文件列表 --> <table id="upload-list"> <thead> <tr> <th width="35%">文件名</th> <th width="15%">文件類型</th> <th width="15%">文件大小</th> <th width="20%">上傳進(jìn)度</th> <th width="15%"> <input type="button" id="upload-all-btn" value="全部上傳"> </th> </tr> </thead> <tbody> </tbody> </table> </form> <!-- 上傳文件列表中每個(gè)文件的信息模版 --> <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>
Jetez les styles CSS ici
<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) Vient ensuite l'analyse de l'implémentation JS
Nous pouvons obtenir des informations sur le fichier via l'objet FileList
La taille est la taille du fichier, le fractionnement des fichiers doit s'appuyer sur cela
La taille ici est le nombre d'octets, donc lorsque l'interface affiche la taille du fichier, il peut être converti comme ceci
// 計(jì)算文件大小 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';
Après avoir sélectionné le fichier, affichez les informations du fichier et remplacez les données dans le modèle
// 更新文件信息列表 uploadItem.push(uploadItemTpl .replace(/{{fileName}}/g, file.name) .replace('{{fileType}}', file.type || file.name.match(/\.\w+$/) + '文件') .replace('{{fileSize}}', size) .replace('{{progress}}', progress) .replace('{{totalSize}}', file.size) .replace('{{uploadVal}}', uploadVal) );
Cependant, lors de l'affichage du informations sur le fichier, peut-être que ce fichier a déjà été téléchargé. Afin de reprendre le téléchargement à partir d'un point d'arrêt, il doit être jugé et invité sur l'interface.
Vérifiez la zone locale pour voir s'il existe des données correspondantes (l'approche ici est que lorsque l'enregistrement local indique que 100?% a été téléchargé, il est directement re-téléchargé au lieu de continuer à télécharger)
// 初始通過(guò)本地記錄,判斷該文件是否曾經(jīng)上傳過(guò) percent = window.localStorage.getItem(file.name + '_p'); if (percent && percent !== '100.0') { progress = '已上傳 ' + percent + '%'; uploadVal = '繼續(xù)上傳'; }
Affiche la liste des informations sur les fichiers
Cliquez pour commencer le téléchargement et vous pourrez télécharger le fichier correspondant
Lors du téléchargement d'un fichier, vous devez diviser le fichier en segments.
Par exemple, chaque segment configuré ici est 1024B, le segment total des morceaux (utilisé pour déterminer s'il s'agit du dernier segment), le segment des morceaux, le pourcentage actuellement téléchargé, etc.
Ce qu'il faut mentionner, c'est l'opération de suspension du téléchargement. En fait, je ne l'ai pas encore implémentée, je n'ai pas d'autre choix que de la mettre en pause...
La prochaine étape est le processus de segmentation
// 設(shè)置分片的開始結(jié)尾 var blobFrom = chunk * eachSize, // 分段開始 blobTo = (chunk + 1) * eachSize > totalSize ? totalSize : (chunk + 1) * eachSize, // 分段結(jié)尾 percent = (100 * blobTo / totalSize).toFixed(1), // 已上傳的百分比 timeout = 5000, // 超時(shí)時(shí)間 fd = new FormData($('#myForm')[0]); fd.append('theFile', findTheFile(fileName).slice(blobFrom, blobTo)); // 分好段的文件 fd.append('fileName', fileName); // 文件名 fd.append('totalSize', totalSize); // 文件總大小 fd.append('isLastChunk', isLastChunk); // 是否為末段 fd.append('isFirstUpload', times === 'first' ? 1 : 0); // 是否是第一段(第一次上傳) // 上傳之前查詢是否以及上傳過(guò)分片 chunk = window.localStorage.getItem(fileName + '_chunk') || 0; chunk = parseInt(chunk, 10);
文件應(yīng)該支持覆蓋上傳,所以如果文件以及上傳完了,現(xiàn)在再上傳,應(yīng)該重置數(shù)據(jù)以支持覆蓋(不然后端就直接追加 blob數(shù)據(jù)了)
// 如果第一次上傳就為末分片,即文件已經(jīng)上傳完成,則重新覆蓋上傳 if (times === 'first' && isLastChunk === 1) { window.localStorage.setItem(fileName + '_chunk', 0); chunk = 0; isLastChunk = 0; }
這個(gè) times 其實(shí)就是個(gè)參數(shù),因?yàn)橐谏弦环侄蝹魍曛笤賯飨乱环侄?,所以這里的做法是在回調(diào)中繼續(xù)調(diào)用這個(gè)上傳操作
接下來(lái)就是真正的文件上傳操作了,用Ajax上傳,因?yàn)橛玫搅薋ormData對(duì)象,所以不要忘了在$.ajax({}加上這個(gè)配置processData: false
上傳了一個(gè)分段,通過(guò)返回的結(jié)果判斷是否上傳完畢,是否繼續(xù)上傳
success: function(rs) { rs = JSON.parse(rs); // 上傳成功 if (rs.status === 200) { // 記錄已經(jīng)上傳的百分比 window.localStorage.setItem(fileName + '_p', percent); // 已經(jīng)上傳完畢 if (chunk === (chunks - 1)) { $progress.text(msg['done']); $this.val('已經(jīng)上傳').prop('disabled', true).css('cursor', 'not-allowed'); if (!$('#upload-list').find('.upload-item-btn:not(:disabled)').length) { $('#upload-all-btn').val('已經(jīng)上傳').prop('disabled', true).css('cursor', 'not-allowed'); } } else { // 記錄已經(jīng)上傳的分片 window.localStorage.setItem(fileName + '_chunk', ++chunk); $progress.text(msg['in'] + percent + '%'); // 這樣設(shè)置可以暫停,但點(diǎn)擊后動(dòng)態(tài)的設(shè)置就暫停不了.. // if (chunk == 10) { // isPaused = 1; // } console.log(isPaused); if (!isPaused) { startUpload(); } } } // 上傳失敗,上傳失敗分很多種情況,具體按實(shí)際來(lái)設(shè)置 else if (rs.status === 500) { $progress.text(msg['failed']); } }, error: function() { $progress.text(msg['failed']); }
2. 后端實(shí)現(xiàn)
要注意一下,通過(guò)FormData對(duì)象上傳的文件對(duì)象,在PHP中也是通過(guò)$_FILES全局對(duì)象獲取的,還有為了避免上傳后文件中文的亂碼,用一下iconv
斷點(diǎn)續(xù)傳支持文件的覆蓋,所以如果已經(jīng)存在完整的文件,就將其刪除
// 如果第一次上傳的時(shí)候,該文件已經(jīng)存在,則刪除文件重新上傳 if ($isFirstUpload == '1' && file_exists('upload/'. $fileName) && filesize('upload/'. $fileName) == $totalSize) { unlink('upload/'. $fileName); }
使用上述的兩個(gè)方法,進(jìn)行文件信息的追加,別忘了加上 FILE_APPEND 這個(gè)參數(shù)~
// 繼續(xù)追加文件數(shù)據(jù) if (!file_put_contents('upload/'. $fileName, file_get_contents($_FILES['theFile']['tmp_name']), FILE_APPEND)) { $status = 501; } else { // 在上傳的最后片段時(shí),檢測(cè)文件是否完整(大小是否一致) if ($isLastChunk === '1') { if (filesize('upload/'. $fileName) == $totalSize) { $status = 200; } else { $status = 502; } } else { $status = 200; } }
一般在傳完后都需要進(jìn)行文件的校驗(yàn)吧,所以這里簡(jiǎn)單校驗(yàn)了文件大小是否一致。
根據(jù)實(shí)際需求的不同有不同的錯(cuò)誤處理方法,這里就先不多處理了
完整的PHP部分
0) { $status = 500; } else { // 此處為一般的文件上傳操作 // if (!move_uploaded_file($_FILES['theFile']['tmp_name'], 'upload/'. $_FILES['theFile']['name'])) { // $status = 501; // } else { // $status = 200; // } // 以下部分為文件斷點(diǎn)續(xù)傳操作 // 如果第一次上傳的時(shí)候,該文件已經(jīng)存在,則刪除文件重新上傳 if ($isFirstUpload == '1' && file_exists('upload/'. $fileName) && filesize('upload/'. $fileName) == $totalSize) { unlink('upload/'. $fileName); } // 否則繼續(xù)追加文件數(shù)據(jù) if (!file_put_contents('upload/'. $fileName, file_get_contents($_FILES['theFile']['tmp_name']), FILE_APPEND)) { $status = 501; } else { // 在上傳的最后片段時(shí),檢測(cè)文件是否完整(大小是否一致) if ($isLastChunk === '1') { if (filesize('upload/'. $fileName) == $totalSize) { $status = 200; } else { $status = 502; } } else { $status = 200; } } } echo json_encode(array( 'status' => $status, 'totalSize' => filesize('upload/'. $fileName), 'isLastChunk' => $isLastChunk )); ?>
? ?
更多Le front-end implémente le téléchargement de reprise de point darrêt des fichiers (soumission de fichiers front-end, réception de fichiers PHP back-end)相關(guān)文章請(qǐng)關(guān)注PHP中文網(wǎng)!

Outils d'IA chauds

Undress AI Tool
Images de déshabillage gratuites

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Clothoff.io
Dissolvant de vêtements AI

Video Face Swap
échangez les visages dans n'importe quelle vidéo sans effort grace à notre outil d'échange de visage AI entièrement gratuit?!

Article chaud

Outils chauds

Bloc-notes++7.3.1
éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Les problèmes et les solutions courants pour la portée de la variable PHP incluent: 1. La variable globale ne peut pas être accessible dans la fonction, et elle doit être transmise en utilisant le mot-clé ou le paramètre global; 2. La variable statique est déclarée avec statique, et elle n'est initialisée qu'une seule fois et la valeur est maintenue entre plusieurs appels; 3. Des variables hyperglobales telles que $ _get et $ _post peuvent être utilisées directement dans n'importe quelle portée, mais vous devez faire attention au filtrage s?r; 4. Les fonctions anonymes doivent introduire des variables de portée parents via le mot clé Utiliser, et lorsque vous modifiez les variables externes, vous devez passer une référence. La ma?trise de ces règles peut aider à éviter les erreurs et à améliorer la stabilité du code.

Pour gérer en toute sécurité les téléchargements de fichiers PHP, vous devez vérifier la source et taper, contr?ler le nom et le chemin du fichier, définir les restrictions du serveur et traiter les fichiers multimédias deux fois. 1. Vérifiez la source de téléchargement pour empêcher le CSRF via le jeton et détecter le type de mime réel via FINFO_FILE en utilisant le contr?le de liste blanche; 2. Renommez le fichier à une cha?ne aléatoire et déterminez l'extension pour la stocker dans un répertoire non Web en fonction du type de détection; 3. La configuration PHP limite la taille de téléchargement et le répertoire temporaire Nginx / Apache interdit l'accès au répertoire de téléchargement; 4. La bibliothèque GD résait les images pour effacer des données malveillantes potentielles.

Il existe trois méthodes courantes pour le code de commentaire PHP: 1. Utiliser // ou # pour bloquer une ligne de code, et il est recommandé d'utiliser //; 2. Utiliser /.../ pour envelopper des blocs de code avec plusieurs lignes, qui ne peuvent pas être imbriquées mais peuvent être croisées; 3. Compétences combinées Commentaires tels que l'utilisation / if () {} / pour contr?ler les blocs logiques, ou pour améliorer l'efficacité avec les touches de raccourci de l'éditeur, vous devez prêter attention aux symboles de fermeture et éviter les nidification lorsque vous les utilisez.

La clé pour rédiger des commentaires PHP est de clarifier l'objectif et les spécifications. Les commentaires devraient expliquer "pourquoi" plut?t que "ce qui a été fait", en évitant la redondance ou trop de simplicité. 1. Utilisez un format unifié, tel que DocBlock (/ * /) pour les descriptions de classe et de méthode afin d'améliorer la lisibilité et la compatibilité des outils; 2. Soulignez les raisons de la logique, telles que pourquoi les sauts JS doivent être sortis manuellement; 3. Ajoutez une description d'une vue d'ensemble avant le code complexe, décrivez le processus dans les étapes et aidez à comprendre l'idée globale; 4. Utilisez TODO et FIXME Rationalement pour marquer des éléments et des problèmes de taches pour faciliter le suivi et la collaboration ultérieurs. De bonnes annotations peuvent réduire les co?ts de communication et améliorer l'efficacité de la maintenance du code.

AgeneratorInphpisamemory-EfficientwaytoterateOrgedatasetsByyieldingValuesonEatatimeIntedofreturningThemallAtonce.1.GeneratorsUsEtheieldKeywordToproduceValuesondemand, ReducingMemoryUsage.2.TheyAreusefulForHandlingBigloops, ReadingLargeFiles, OR OR.

Toléarnphpeffective, startBySettingUpAlocalServerERironmentUsingToolsLILYXAMPPANDACODEDITERLIGHILLEVSCODE.1) INSTRUSITIONXAMPFORAPACHE, MYSQL, ANDPHP.2) USACODEDEDITORFORSYNTAXSUPPORT.3)

En PHP, vous pouvez utiliser des crochets ou des accolades bouclées pour obtenir des caractères d'index spécifiques à la cha?ne, mais les crochets sont recommandés; L'index commence à partir de 0 et l'accès à l'extérieur de la plage renvoie une valeur nulle et ne peut pas se voir attribuer une valeur; MB_substr est nécessaire pour gérer les caractères multi-octets. Par exemple: $ str = "Hello"; echo $ str [0]; sortie h; et les caractères chinois tels que MB_substr ($ str, 1,1) doivent obtenir le résultat correct; Dans les applications réelles, la longueur de la cha?ne doit être vérifiée avant le boucle, les cha?nes dynamiques doivent être vérifiées pour la validité et les projets multilingues recommandent d'utiliser des fonctions de sécurité multi-octets uniformément.

Toinstallphpquickly, usexAmpPonWindowsorHomebrewonMacos.1.onwindows, downloadAndInstallxAmppp, selectComponents, startapache et placefilesInhtdocs.2.
