


Partagez un exemple de tutoriel sur le principe d'implémentation du composant de téléchargement d'images (React + Node)
Cet article présente principalement l'exemple de code d'implémentation du composant Reactpictureupload basé sur Node, qui est d'une grande valeur pratique. Les amis qui en ont besoin peuvent s'y référer. à cela
est écrit devant
Si le drapeau rouge ne tombe pas, je m'engage à exécuter JavaScript jusqu'au bout ! Aujourd'hui, je vais vous présenter les principes d'implémentation front-end et back-end (React + Node) du composant de téléchargement d'images dans mon projet open source Royal. Cela m'a pris du temps et j'espère que cela vous sera utile.
Implémentation front-end
Suite à l'idée de la composantisation React, j'ai fait télécharger l'image d'un composant indépendant (non autre dépendance), importez-le simplement directement.
import React, { Component } from 'react' import Upload from '../../components/FormControls/Upload/' //...... render() { return ( <p><Upload uri={'http://jafeney.com:9999/upload'} /></p> ) }
Le paramètre uri doit être transmis, qui est l'adresse de l'interface du backend pour le téléchargement de l'image. La façon d'écrire l'interface sera discutée ci-dessous.
Page de rendu
La partie rendu du composant doit refléter trois fonctions :
Sélection d'image ( fenêtre de dialogue)
Fonction pouvant être glissée (conteneur de déplacement)
Prévisualisable (liste d'aperçu)
Télécharger bouton (bouton)
Télécharger l'adresse et le lien de l'image terminée (liste d'informations)
Principal renderFonction
render() { return ( <form action={this.state.uri} method="post" encType="multipart/form-data"> <p className="ry-upload-box"> <p className="upload-main"> <p className="upload-choose"> <input onChange={(v)=>this.handleChange(v)} type="file" size={this.state.size} name="fileSelect" accept="image/*" multiple={this.state.multiple} /> <span ref="dragBox" onDragOver={(e)=>this.handleDragHover(e)} onDragLeave={(e)=>this.handleDragHover(e)} onDrop={(e)=>this.handleDrop(e)} className="upload-drag-area"> 或者将图片拖到此处 </span> </p> <p className={this.state.files.length? "upload-preview":"upload-preview ry-hidden"}> { this._renderPreview(); // 渲染图片预览列表 } </p> </p> <p className={this.state.files.length? "upload-submit":"upload-submit ry-hidden"}> <button type="button" onClick={()=>this.handleUpload()} class="upload-submit-btn"> 确认上传图片 </button> </p> <p className="upload-info"> { this._renderUploadInfos(); // 渲染图片上传信息 } </p> </p> </form> ) }
Liste d'aperçu des images rendues
_renderPreview() { if (this.state.files) { return this.state.files.map((item, idx) => { return ( <p className="upload-append-list"> <p> <strong>{item.name}</strong> <a href="javascript:void(0)" rel="external nofollow" className="upload-delete" title="删除" index={idx}></a> <br/> <img src={item.thumb} className="upload-image" /> </p> <span className={this.state.progress[idx]? "upload-progress": "upload-progress ry-hidden"}> {this.state.progress[idx]} </span> </p> ) }) } else { return null } }
Liste d'informations de téléchargement des images rendues
_renderUploadInfos() { if (this.state.uploadHistory) { return this.state.uploadHistory.map((item, idx) => { return ( <p> <span>上传成功,图片地址是:</span> <input type="text" class="upload-url" value={item.relPath}/> <a href={item.relPath} target="_blank">查看</a> </p> ); }) } else { return null; } }
Le principe du téléchargement d'images sur le front-end est de construire l'objet FormData, d'append() l'objet fichier à l'objet, puis de le monter en XMLSend() sur l'objet HttpRequest vers le serveur.
Obtenir l'objet fichier
Pour obtenir l'objet fichier, vous devez utiliser l'événement change de la zone de saisie pour obtenir le handle paramètre e
onChange={(e)=>this.handleChange(e)}
Ensuite, effectuez le traitement suivant :
e.preventDefault() let target = event.target let files = target.files let count = this.state.multiple ? files.length : 1 for (let i = 0; i < count; i++) { files[i].thumb = URL.createObjectURL(files[i]) } // 转换为真正的数组 files = Array.prototype.slice.call(files, 0) // 过滤非图片类型的文件 files = files.filter(function (file) { return /image/i.test(file.type) })
À ce stade, les fichiers sont un tableau d'objets fichiers dont nous avons besoin et le concatérons dans les fichiers d'origine.
this.setState({files: this.state.files.concat(files)})
De cette façon, l'opération suivante peut obtenir le fichier image actuellement sélectionné via this.state.files.
Utilisez Promise pour gérer le téléchargement asynchrone
Le téléchargement de fichiers est asynchrone par rapport au navigateur Afin de gérer le téléchargement multi-images ultérieur, Promise est introduit ici pour gérer l'asynchrone. Fonctionnement :
upload(file, idx) { return new Promise((resolve, reject) => { let xhr = new XMLHttpRequest() if (xhr.upload) { // 上传中 xhr.upload.addEventListener("progress", (e) => { // 处理上传进度 this.handleProgress(file, e.loaded, e.total, idx); }, false) // 文件上传成功或是失败 xhr.onreadystatechange = (e) => { if (xhr.readyState === 4) { if (xhr.status === 200) { // 上传成功操作 this.handleSuccess(file, xhr.responseText) // 把该文件从上传队列中删除 this.handleDeleteFile(file) resolve(xhr.responseText); } else { // 上传出错处理 this.handleFailure(file, xhr.responseText) reject(xhr.responseText); } } } // 开始上传 xhr.open("POST", this.state.uri, true) let form = new FormData() form.append("filedata", file) xhr.send(form) }) }
Calcul de la progression du téléchargement
L'avantage d'utiliser l'objet XMLHttpRequest pour envoyer des requêtes asynchrones est qu'il peut calculer la progression du traitement des requêtes, qui récupère n'a pas.
Nous pouvons ajouter une surveillance d'événement pour l'événement de progression de l'objet xhr.upload :
xhr.upload.addEventListener("progress", (e) => { // 处理上传进度 this.handleProgress(file, e.loaded, e.total, i); }, false)
Explication : Le paramètre idx est le index qui enregistre la file d'attente de téléchargement multi-images
handleProgress(file, loaded, total, idx) { let percent = (loaded / total * 100).toFixed(2) + '%'; let _progress = this.state.progress; _progress[idx] = percent; this.setState({ progress: _progress }) // 反馈到DOM里显示 }
Téléchargement par glisser-déposer
Le glisser-déposer de fichiers est en fait très simple pour HTML5 car il vient avec plusieurs écouteurs d'événements Le mécanisme peut effectuer ce type de traitement directement. Les trois suivants sont principalement utilisés :
onDragOver={(e)=>this.handleDragHover(e)} onDragLeave={(e)=>this.handleDragHover(e)} onDrop={(e)=>this.handleDrop(e)}
Comportement du navigateur lors de l'annulation du glisser-déposer :
handleDragHover(e) { e.stopPropagation() e.preventDefault() }
Traitement des fichiers glissés :
handleDrop(e) { this.setState({progress:[]}) this.handleDragHover(e) // 获取文件列表对象 let files = e.target.files || e.dataTransfer.files let count = this.state.multiple ? files.length : 1 for (let i = 0; i < count; i++) { files[i].thumb = URL.createObjectURL(files[i]) } // 转换为真正的数组 files = Array.prototype.slice.call(files, 0) // 过滤非图片类型的文件 files = files.filter(function (file) { return /image/i.test(file.type) }) this.setState({files: this.state.files.concat(files)}) }
Télécharger plusieurs images en même temps
Prend en charge plusieurs téléchargements d'images. Nous devons définir l'attribut au point d'appel du composant :
multiple = { true } // 开启多图上传 size = { 50 } // 一次最大上传数量(虽没有上限,为保证服务端正常,建议50以下)
Ensuite. nous pouvons utiliser Promise.all() pour gérer la file d'attente des opérations asynchrones :
handleUpload() { let _promises = this.state.files.map((file, idx) => this.upload(file, idx)) Promise.all(_promises).then( (res) => { // 全部上传完成 this.handleComplete() }).catch( (err) => { console.log(err) }) }
D'accord, le travail frontal est terminé et la prochaine étape est le travail de Node.
Implémentation du backend
Pour plus de commodité, le backend utilise le framework express pour créer rapidement des services et un routage HTTP. Pour des projets spécifiques, voir mon github node-image-upload. Bien que la logique soit simple, il y a quand même plusieurs points remarquables :
Appel cross-domain
Le backend de ce projet utilise express, on peut utiliser res .header( ) définit la "source autorisée" de la requête pour autoriser les appels inter-domaines :
res.header('Access-Control-Allow-Origin', '*');
est défini sur * pour autoriser toute source d'accès, qui est moins sécurisée. Il est recommandé de le définir sur le nom de domaine de deuxième niveau dont vous avez besoin, tel que jafeney.com.
En plus de « Autoriser la source », d'autres incluent « Autoriser l'en-tête », « Autoriser le domaine », « Autoriser la méthode », « Type de texte », etc. Les paramètres couramment utilisés sont les suivants :
function allowCross(res) { res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild'); res.header('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS'); res.header("X-Powered-By",' 3.2.1') res.header("Content-Type", "application/json;charset=utf-8"); }
Requête Ajax sous ES6
La requête Ajax sous ES6 est différente de celle d'ES5 et sera réinitialisée avant la demande formelle est émis. Envoyez d'abord une requête de type OPTIONS à titre de test. Ce n'est que lorsque la requête est réussie que la requête formelle peut être envoyée au serveur.
所以服务端路由 我们还需要 处理这样一个 请求:
router.options('*', function (req, res, next) { res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild'); res.header('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS'); res.header("X-Powered-By",' 3.2.1') res.header("Content-Type", "application/json;charset=utf-8"); next(); });
注意:该请求同样需要设置跨域。
处理上传
处理上传的图片引人了multiparty模块,用法很简单:
/*使用multiparty处理上传的图片*/ router.post('/upload', function(req, res, next) { // 生成multiparty对象,并配置上传目标路径 var form = new multiparty.Form({uploadDir: './public/file/'}); // 上传完成后处理 form.parse(req, function(err, fields, files) { var filesTmp = JSON.stringify(files, null, 2); var relPath = ''; if (err) { // 保存失败 console.log('Parse error: ' + err); } else { // 图片保存成功! console.log('Parse Files: ' + filesTmp); // 图片处理 processImg(files); } }); });
图片处理
Node处理图片需要引入 gm 模块,它需要用 npm 来安装:
npm install gm --save
BUG说明
注意:node的图形操作gm模块前使用必须 先安装 imagemagick 和 graphicsmagick,Linux (ubuntu)上使用apt-get 安装:
sudo apt-get install imagemagick sudo apt-get install graphicsmagick --with-webp // 支持webp格式的图片
MacOS上可以用 Homebrew 直接安装:
brew install imagemagick brew install graphicsmagick --with-webp // 支持webp格式的图片
预设尺寸
有些时候除了原图,我们可能需要把原图等比例缩小作为预览图或者缩略图。这个异步操作还是用Promise来实现:
function reSizeImage(paths, dstPath, size) { return new Promise(function(resolve, reject) { gm(dstPath) .noProfile() .resizeExact(size) .write('.' + paths[1] + '@' + size + '00.' + paths[2], function (err) { if (!err) { console.log('resize as ' + size + ' ok!') resolve() } else { reject(err) }; }); }); }
重命名图片
为了方便排序和管理图片,我们按照 “年月日 + 时间戳 + 尺寸” 来命名图片:
var _dateSymbol = new Date().toLocaleDateString().split('-').join(''); var _timeSymbol = new Date().getTime().toString();
至于图片尺寸 使用 gm的 size() 方法来获取,处理方式如下:
gm(uploadedPath).size(function(err, size) { var dstPath = './public/file/' + _dateSymbol + _timeSymbol + '_' + size.width + 'x' + size.height + '.' + _img.originalFilename.split('.')[1]; var _port = process.env.PORT || '9999'; relPath = 'http://' + req.hostname + ( _port!==80 ? ':' + _port : '' ) + '/file/' + _dateSymbol + _timeSymbol + '_' + size.width + 'x' + size.height + '.' + _img.originalFilename.split('.')[1]; // 重命名 fs.rename(uploadedPath, dstPath, function(err) { if (err) { reject(err) } else { console.log('rename ok!'); } }); });
总结
对于大前端的工作,理解图片上传的前后端原理仅仅是浅层的。我们的口号是 “把JavaScript进行到底!”,现在无论是 ReactNative的移动端开发,还是NodeJS的后端开发,前端工程师可以做的工作早已不仅仅是局限于web页面,它已经渗透到了互联网应用层面的方方面面,或许,叫 全栈工程师 更为贴切吧。
【相关推荐】
1. 免费js在线视频教程
3. php.cn独孤九贱(3)-JavaScript视频教程
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Outils d'IA chauds

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.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

Video Face Swap
Échangez les visages dans n'importe quelle vidéo sans effort grâce à 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)

Sujets chauds





Comment créer une application de chat en temps réel à l'aide de React et WebSocket Introduction : Avec le développement rapide d'Internet, la communication en temps réel a attiré de plus en plus d'attention. Les applications de chat en direct font désormais partie intégrante de la vie sociale et professionnelle moderne. Cet article expliquera comment créer une application simple de chat en temps réel à l'aide de React et WebSocket, et fournira des exemples de code spécifiques. 1. Préparation technique Avant de commencer à créer une application de chat en temps réel, nous devons préparer les technologies et outils suivants : React : un pour la construction

Guide de séparation front-end et back-end de React : Comment réaliser un découplage front-end et back-end et un déploiement indépendant, des exemples de code spécifiques sont nécessaires Dans l'environnement de développement Web actuel, la séparation front-end et back-end est devenue une tendance. En séparant le code front-end et back-end, le travail de développement peut être rendu plus flexible, plus efficace et faciliter la collaboration en équipe. Cet article expliquera comment utiliser React pour réaliser une séparation front-end et back-end, atteignant ainsi les objectifs de découplage et de déploiement indépendant. Tout d’abord, nous devons comprendre ce qu’est la séparation front-end et back-end. Dans le modèle de développement Web traditionnel, le front-end et le back-end sont couplés

Comment utiliser React et Flask pour créer des applications Web simples et faciles à utiliser Introduction : Avec le développement d'Internet, les besoins des applications Web deviennent de plus en plus diversifiés et complexes. Afin de répondre aux exigences des utilisateurs en matière de facilité d'utilisation et de performances, il devient de plus en plus important d'utiliser des piles technologiques modernes pour créer des applications réseau. React et Flask sont deux frameworks très populaires pour le développement front-end et back-end, et ils fonctionnent bien ensemble pour créer des applications Web simples et faciles à utiliser. Cet article détaillera comment exploiter React et Flask

Comment créer une application de messagerie fiable avec React et RabbitMQ Introduction : Les applications modernes doivent prendre en charge une messagerie fiable pour obtenir des fonctionnalités telles que les mises à jour en temps réel et la synchronisation des données. React est une bibliothèque JavaScript populaire pour créer des interfaces utilisateur, tandis que RabbitMQ est un middleware de messagerie fiable. Cet article explique comment combiner React et RabbitMQ pour créer une application de messagerie fiable et fournit des exemples de code spécifiques. Présentation de RabbitMQ :

Guide de l'utilisateur de ReactRouter : Comment implémenter le contrôle du routage frontal Avec la popularité des applications monopage, le routage frontal est devenu un élément important qui ne peut être ignoré. En tant que bibliothèque de routage la plus populaire de l'écosystème React, ReactRouter fournit des fonctions riches et des API faciles à utiliser, rendant la mise en œuvre du routage frontal très simple et flexible. Cet article expliquera comment utiliser ReactRouter et fournira quelques exemples de code spécifiques. Pour installer ReactRouter en premier, nous avons besoin

Comment utiliser React et Apache Kafka pour créer des applications de traitement de données en temps réel Introduction : Avec l'essor du Big Data et du traitement de données en temps réel, la création d'applications de traitement de données en temps réel est devenue la priorité de nombreux développeurs. La combinaison de React, un framework front-end populaire, et d'Apache Kafka, un système de messagerie distribué hautes performances, peut nous aider à créer des applications de traitement de données en temps réel. Cet article expliquera comment utiliser React et Apache Kafka pour créer des applications de traitement de données en temps réel, et

L'applet WeChat implémente la fonction de téléchargement d'images Avec le développement de l'Internet mobile, l'applet WeChat est devenue un élément indispensable dans la vie des gens. Les mini-programmes WeChat fournissent non seulement une multitude de scénarios d'application, mais prennent également en charge les fonctions définies par les développeurs, notamment les fonctions de téléchargement d'images. Cet article présentera comment implémenter la fonction de téléchargement d'images dans l'applet WeChat et fournira des exemples de code spécifiques. 1. Travaux préparatoires Avant de commencer à écrire du code, nous devons télécharger et installer les outils de développement WeChat et nous inscrire en tant que développeur WeChat. En même temps, vous devez également comprendre WeChat

Explication détaillée et guide d'installation pour les nœuds de pignon Cet article introduira l'écosystème de pignon en détail - nœuds PI, un rôle clé dans l'écosystème de pignon et fournir des étapes complètes pour l'installation et la configuration. Après le lancement du réseau de test de la blockchain pèse, les nœuds PI sont devenus une partie importante de nombreux pionniers participant activement aux tests, se préparant à la prochaine version du réseau principal. Si vous ne connaissez pas encore Pinetwork, veuillez vous référer à ce qu'est Picoin? Quel est le prix de l'inscription? PI Utilisation, exploitation minière et sécurité. Qu'est-ce que Pinetwork? Le projet Pinetwork a commencé en 2019 et possède sa pièce exclusive de crypto-monnaie PI. Le projet vise à en créer un que tout le monde peut participer
