使用React上載,操縱圖像
下面是由 Damon Bauer 發的一篇帖子,他做著一份很常見的web開發工作: 給用戶提供圖片上傳的方法. 很難說這件事比較簡單, 但是在一些強大的工具幫助下也可以完成這樣的工作, 而且比之前更加容易. demon甚至全部在瀏覽器中完成這項工作 實例 鏈接 ! web開發者常做的一件事情就是提供用戶上傳圖片的解決方案,看上去微不足道的,但是當構建一個上傳組件的時候 需要考慮以下幾點:
-
你允許用戶上傳什么格式的圖片?
-
圖片需要保證多大? 這將如何影響性能?
-
圖片應該是什么樣的長寬比?
-
圖像將如何組織?不合適的圖像如何被捕獲?
-
圖片將托管在哪里?如何進行管理?
服務端工具 如 Paperclip 和 ImageProcessor 為以上考慮提供了解決方案. 不幸的是,在單頁應用中沒有一個現成的工具可以使用 (我發現). 在這里我將會告訴你如何在 React 應用中不使用后端語言實現它.
下面是我們將會構建的示例圖:
工具包
我用到了以下這些工具:
-
react-dropzone 從一個用戶那里獲取圖片
-
superagent 為了轉移上傳的圖片
-
Cloudinary 存儲和操作圖片
建立一個 Cloudinary
Cloudinary 是一個基于云的服務,您可以存儲,處理,管理和提供圖像。我選擇使用Cloudinary,因為它有一個免費的版本,包括我需要的所有功能。你至少需要一個免費帳戶上手。
比方說,你要裁切,重新調整和為上傳的圖片加一個篩選器。 Cloudinary有 transformations 的概念,就是它需要和你需要修改的圖像鏈接在一起。上傳后,轉換就會發生,修改和保存新的圖片。
在 Cloudinary 控制臺, 選擇 Settings > Upload 之后 選擇 "Add upload preset" 在上傳預置項中.
在下面的屏幕,修改“模式”為“無簽名”。這是必要的,這樣你可以不使用服務器端語言協商的私鑰上傳到Cloudinary。
通過在“傳入轉換”中選擇“編輯”添加你想要的轉換。在這里,您可以裁剪,調整大小,質量的變化,旋轉,過濾等保存預設,就是這樣!現在,您可以上傳,處理,存儲和圖像服務為您的應用程序。注意 preset ,我們將在以后使用它。現在讓我們繼續前進的代碼。
獲取用戶輸入
為了處理圖像上傳, 我使用了 react-dropzone . 它包括的功能,如拖放,文件類型限制,多文件上傳。
首先,安裝的依賴關系。在命令行中運行:
npm install react react-dropzone superagent --save`
然后在你組件中 引入 React , react-dropzone , 和 superagent . 我使用 the ES6 import 語法:
import React from 'react';
import Dropzone from 'react-dropzone';
import request from 'superagent';
我們之后會使用 superagent . 但現在, 在你組件的渲染方法中, 包括一個 react-dropzone 實例:
export default class ContactForm extends React.Component {
render() {
<Dropzone
multiple={false}
accept="image/*"
onDrop={this.onImageDrop.bind(this)}>
<p>Drop an image or click to select a file to upload.</p>
</Dropzone>
}
下面是組件運行的要點:
-
multiple={false} 允許用戶只能一次性上傳一張圖片.
-
accept="image/*" 允許任何種類的圖片.你可以更明確的限制只有特定的文件類型, e.g. accept="image/jpg,image/png" .
-
onDrop 當圖像被上傳的觸發方法.
當時有 React ES5 類 語法 ( React.createClass ), 所有方法都是 "自動綁定" 到類實例. 這篇文章代碼使用ES6類型語法 ( extends React.Component ), 不提供自動綁定. 這是我們為什么使用 .bind(this) 在 onDrop 屬性. (如果你不熟悉 .bind , 你可以 read about it here .
處理圖像拖放
現在,讓我們設置一個圖像上傳之后的方法。
首先, 設置一個 const 包括上傳重要的兩條信息:
-
上傳預設ID(在創建上傳預設自動創建)
-
你的 Cloudinary 上傳 URL
// import statements
const CLOUDINARY_UPLOAD_PRESET = 'your_upload_preset_id';
const CLOUDINARY_UPLOAD_URL = 'https://api.cloudinary.com/v1_1/your_cloudinary_app_name/upload';
export default class ContactForm extends React.Component {
// render()
接下來,添加組件初始化狀態入口(using this.setState );我稱之為 UploadedFileCloudinaryUrl 。最終,這將持有Cloudinary創建上傳的圖片的URL。稍后,我們將使用這一塊的狀態。
export default class ContactForm extends React.Component {
constructor(props) {
super(props);
this.state = {
uploadedFileCloudinaryUrl: ''
};
}
react-dropzone 文檔狀態 總是會 返回一個上傳文件的數組, 之后我們會傳遞參數到 files 參數 在 onImageDrop 方法. 只要我們允許一次只能傳遞一張圖片, 我們知道,在圖像始終處于所述數組的第一位置.
Call handleImageUpload , 傳遞圖片 ( files[0] ) 到這個方法. 我把它分成幾個獨立的方法, 遵從 Single responsibility principle 的規則. 重要地, 這個原則教你的方法保持緊湊,只做一件事。
export default class ContactForm extends React.Component {
constructor(props) { ... }
onImageDrop(files) {
this.setState({
uploadedFile: files[0]
});
this.handleImageUpload(files[0]);
}
render() { ... }
}
處理圖像上載和傳送
首先, 使用 superagent 上傳到 Cloudinary 使用我們之前設置的倆個 const . 使用 .field method 可以對POST請求綁定數據.這個類型的數據包括所有的Cloudinary 處理圖片的信息. 通過調用 .end , 請求被執行 并且會提供一個回調.
export default class ContactForm extends React.Component {
constructor(props) { ... }
onImageDrop(files) { ... }
handleImageUpload(file) {
let upload = request.post(CLOUDINARY_UPLOAD_URL)
.field('upload_preset', CLOUDINARY_UPLOAD_PRESET)
.field('file', file);
upload.end((err, response) => {
if (err) {
console.error(err);
}
if (response.body.secure_url !== '') {
this.setState({
uploadedFileCloudinaryUrl: response.body.secure_url
});
}
});
}
render() { ... }
}
在 .end 回調里,我記錄返回的任何錯誤。同時這也可能是最好的方法告訴大家,發生了錯誤。
下一步,我們檢查我們是否收到包含一個URL的響應的非空字符串。如果答案是肯定的,那么圖像上載和操縱和Cloudinary產生一個URL。例如,如果一個用戶編輯他們的個人資料并上傳的圖片,您可以從Cloudinary獲得新的圖像URL并存儲在數據庫中。
因此到目前為止,我已經寫的代碼,用戶可以刪除一個圖像 并且組件將其發送到Cloudinary之后提供變換的圖像URL讓我們使用。
繼續渲染
組件的最后一部分是一個 div 預覽上傳的圖片。
export default class ContactForm extends React.Component {
constructor(props) { ... }
onImageDrop(files) { ... }
handleImageUpload(file) { ... }
render() {
<div>
<div className="FileUpload">
...
</div>
<div>
{this.state.uploadedFileCloudinaryUrl === '' ? null :
<div>
<p>{this.state.uploadedFile.name}</p>
<img src={this.state.uploadedFileCloudinaryUrl} />
</div>}
</div>
</div>
}
三元運算符輸出 null (nothing) 如果 uploadedFileCloudinaryUrl 狀態是一個空的字符串.默認重新調用, 我們設置組件的 uploadedFileCloudinaryUrl 狀態為一個空的字符串; 這意味著當組件渲染了, 這個 div 將會為空.
然而, 當 Cloudinary 回應一個 URL, 狀態不再是一個空的URL, 因為我們在 handleImageUpload 中更新了狀態. 這時, 組件將會重新渲染, 顯示上傳文件的名稱 并且展示修改后的圖像.
打包
這僅僅是一個圖像上傳組件的基礎。還有很多你可以添加的特性,如:
-
允許上傳多張圖片
-
刪除上傳的圖片
-
如果上傳由于某種原因失顯示錯誤
-
使用移動設備的攝像頭作為上載源
到目前為止,這種設置很適合我的需求。必須硬編碼上傳的預設是不完美的,但我還沒有遇到任何與它相關問題。
幸運地,你已經理解了如何使用React上傳,存儲,并沒有使用的服務器端語言來處理圖像。如果您有任何問題或意見,我很樂意聽到他們的聲音!我創建了一個庫,在這里,你可以 點擊這里 看到.
來自:http://www.zcfy.cc/article/image-upload-and-manipulation-with-react-1114.html