画像アップロードコンポーネント (React + Node) の実装原理に関するサンプルチュートリアルを共有します。
この記事では、主に Node に基づいた Reactpictureupload コンポーネントの実装例を紹介します。これは非常に実用的であり、必要な方は参考にしてください
前に書いてください。赤旗は降らない、JavaScript
最後まで行くことを約束する!今日は、私のオープンソース プロジェクト Royal の画像アップロード コンポーネントのフロントエンドとバックエンドの実装原則 (React + Node) を紹介します。少し時間がかかりましたが、お役に立てれば幸いです。フロントエンドの実装
React コンポーネント化のアイデアに従って、画像を直接インポートできる独立したコンポーネント (他の依存関係なし) にアップロードするようにしました。
import React, { Component } from 'react' import Upload from '../../components/FormControls/Upload/' //...... render() { return ( <p><Upload uri={'http://jafeney.com:9999/upload'} /></p> ) }
インターフェース
アドレスです。インターフェースの記述方法については後述します。コンポーネントのレンダリング部分は、次の 3 つの機能を反映する必要があります:
画像の選択 (ダイアログ ウィンドウ)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> ) }
_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 } }
_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; } }
フロントエンドでの画像アップロードの原則は、FormDataオブジェクト
を構築し、ファイルオブジェクトをオブジェクトにappend()して、それをXMLHttpRequestオブジェクトにマウントすることです。 send() をサーバーに送信します。 ファイルオブジェクトの取得
ファイルオブジェクトを取得するには、入力ボックスの変更イベント
を使用してハンドルパラメータeonChange={(e)=>this.handleChange(e)}
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) })
this.setState({files: this.state.files.concat(files)})
非同期アップロードを処理するには Promise を使用します
ファイルのアップロードはブラウザに対して非同期です。後続の複数画像のアップロードを処理するために、非同期操作を処理するために Promise が導入されています。 XMLHttpRequest オブジェクトを使用して非同期リクエストを行う利点は、フェッチにはないリクエスト処理の進行状況を計算できることです。
xhr.upload オブジェクトの進行状況イベントのイベント監視を追加できます:
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) }) }
説明: idx パラメーターは、複数画像のアップロード キューを記録する インデックスです
xhr.upload.addEventListener("progress", (e) => { // 处理上传进度 this.handleProgress(file, e.loaded, e.total, i); }, false)
ドラッグ アンド ドロップ アップロード
HTML5 用のファイルのドラッグ アンド ドロップ
このタイプの処理を直接処理できるいくつかのイベント リスニング メカニズムが付属しているため、これは実際には非常に簡単です。主に次の 3 つが使用されます: 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里显示
}
onDragOver={(e)=>this.handleDragHover(e)} onDragLeave={(e)=>this.handleDragHover(e)} onDrop={(e)=>this.handleDrop(e)}
ドラッグされたファイルの処理: handleDragHover(e) {
e.stopPropagation()
e.preventDefault()
}
複数の画像のアップロードをサポートするには、コンポーネントを追加する必要があります呼び出しサイトで
属性を設定します:
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)}) }
その後、Promise.all() を使用して非同期操作キューを処理できます:
multiple = { true } // 开启多图上传 size = { 50 } // 一次最大上传数量(虽没有上限,为保证服务端正常,建议50以下)
さて、フロントエンドの作業は完了しました。次のステップは作業です。ノードの。
バックエンドの実装フレームワークを使用して、HTTP サービスとルーティングを迅速に構築します。特定のプロジェクトについては、私の github のノードイメージアップロードを参照してください。ロジックは単純ですが、いくつかの注目すべき点があります:
クロスドメイン呼び出しこのプロジェクトのバックエンドは、res.header() を通じてリクエストの「許可されたソース」を設定できます。 -domain 呼び出し:
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) }) }
* に設定すると、あらゆるアクセス ソースが許可されますが、安全性は低くなります。 jafeney.com など、必要な第 2 レベルのドメイン名に設定することをお勧めします。 「ソースを許可」の他に、「ヘッダーを許可」、「ドメインを許可」、「メソッドを許可」、「テキストタイプ」などが含まれます。一般的に使用される設定は次のとおりです。
res.header('Access-Control-Allow-Origin', '*');
ES6 での Ajax リクエスト
ES6 での Ajax リクエストは、正式なリクエストが発行される前に、テストとして OPTIONS タイプのリクエストが送信されます。リクエストが成功すると、正式なリクエストをサーバーに送信できます。
所以服务端路由 我们还需要 处理这样一个 请求:
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视频教程
以上が画像アップロードコンポーネント (React + Node) の実装原理に関するサンプルチュートリアルを共有します。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









React と WebSocket を使用してリアルタイム チャット アプリケーションを構築する方法 はじめに: インターネットの急速な発展に伴い、リアルタイム コミュニケーションがますます注目を集めています。ライブチャット アプリは、現代の社会生活や仕事生活に不可欠な部分になっています。この記事では、React と WebSocket を使用して簡単なリアルタイム チャット アプリケーションを構築する方法と、具体的なコード例を紹介します。 1. 技術的な準備 リアルタイム チャット アプリケーションの構築を開始する前に、次のテクノロジとツールを準備する必要があります。 React: 構築用の 1 つ

React フロントエンドとバックエンドの分離ガイド: フロントエンドとバックエンドの分離と独立したデプロイメントを実現する方法、特定のコード例が必要です 今日の Web 開発環境では、フロントエンドとバックエンドの分離がトレンドになっています。フロントエンド コードとバックエンド コードを分離することで、開発作業がより柔軟かつ効率的になり、チームのコラボレーションが促進されます。この記事では、React を使用してフロントエンドとバックエンドの分離を実現し、それによって分離と独立したデプロイの目標を達成する方法を紹介します。まず、フロントエンドとバックエンドの分離とは何かを理解する必要があります。従来の Web 開発モデルでは、フロントエンドとバックエンドが結合されています。

React と Flask を使用してシンプルで使いやすい Web アプリケーションを構築する方法 はじめに: インターネットの発展に伴い、Web アプリケーションのニーズはますます多様化および複雑化しています。使いやすさとパフォーマンスに対するユーザーの要件を満たすために、最新のテクノロジー スタックを使用してネットワーク アプリケーションを構築することがますます重要になっています。 React と Flask は、フロントエンドおよびバックエンド開発用の 2 つの非常に人気のあるフレームワークであり、うまく連携してシンプルで使いやすい Web アプリケーションを構築します。この記事では、React と Flask を活用する方法について詳しく説明します。

React と RabbitMQ を使用して信頼性の高いメッセージング アプリケーションを構築する方法 はじめに: 最新のアプリケーションは、リアルタイム更新やデータ同期などの機能を実現するために、信頼性の高いメッセージングをサポートする必要があります。 React はユーザー インターフェイスを構築するための人気のある JavaScript ライブラリであり、RabbitMQ は信頼性の高いメッセージング ミドルウェアです。この記事では、React と RabbitMQ を組み合わせて信頼性の高いメッセージング アプリケーションを構築する方法を紹介し、具体的なコード例を示します。 RabbitMQ の概要:

ReactRouter ユーザーガイド: フロントエンドルーティング制御の実装方法 シングルページアプリケーションの人気に伴い、フロントエンドルーティングは無視できない重要な部分になりました。 React エコシステムで最も人気のあるルーティング ライブラリとして、ReactRouter は豊富な機能と使いやすい API を提供し、フロントエンド ルーティングの実装を非常にシンプルかつ柔軟にします。この記事では、ReactRouter の使用方法と具体的なコード例を紹介します。 ReactRouter を最初にインストールするには、次のものが必要です

React と Apache Kafka を使用してリアルタイム データ処理アプリケーションを構築する方法 はじめに: ビッグ データとリアルタイム データ処理の台頭により、リアルタイム データ処理アプリケーションの構築が多くの開発者の追求となっています。人気のあるフロントエンド フレームワークである React と、高性能分散メッセージング システムである Apache Kafka を組み合わせることで、リアルタイム データ処理アプリケーションを構築できます。この記事では、React と Apache Kafka を使用してリアルタイム データ処理アプリケーションを構築する方法を紹介します。

WeChat アプレットが画像アップロード機能を実装 モバイル インターネットの発展に伴い、WeChat アプレットは人々の生活に欠かせないものになりました。 WeChat ミニ プログラムは、豊富なアプリケーション シナリオを提供するだけでなく、画像アップロード機能などの開発者定義の機能もサポートします。この記事では、WeChat アプレットに画像アップロード機能を実装する方法と具体的なコード例を紹介します。 1. 準備作業 コードを書き始める前に、WeChat 開発者ツールをダウンロードしてインストールし、WeChat 開発者として登録する必要があります。同時に、WeChat についても理解する必要があります。

ピン張りのノードの詳細な説明とインストールガイドこの記事では、ピネットワークのエコシステムを詳細に紹介します - PIノードは、ピン系生態系における重要な役割であり、設置と構成の完全な手順を提供します。 Pinetworkブロックチェーンテストネットワークの発売後、PIノードは多くの先駆者の重要な部分になり、テストに積極的に参加し、今後のメインネットワークリリースの準備をしています。まだピン張りのものがわからない場合は、ピコインとは何かを参照してください。リストの価格はいくらですか? PIの使用、マイニング、セキュリティ分析。パインワークとは何ですか?ピン競技プロジェクトは2019年に開始され、独占的な暗号通貨PIコインを所有しています。このプロジェクトは、誰もが参加できるものを作成することを目指しています
