ruby on rails爬坑(三):圖片上傳及顯示


一,問題及思路

最近在用rails + react + mysql基本框架寫一個cms + client的項目,里面涉及到了圖片的上傳及顯示,下面簡單說說思路,至於這個項目的配置部署,應該會在寒假結束總結分享一下。

rails中圖片上傳及顯示要解決主要問題是:

  • 圖片存在哪?
  • 圖片格式大小?
  • 客戶端怎么顯示圖片?

因為這是個小項目,估計最多1000張圖片,最多占用空間1G,所以采取相對簡便的方法:圖片保存在rails的public文件夾里(也就是保存在部署該項目的主機中),如果圖片比較多的話,還是推薦用亞馬遜雲提供的服務AWS S3(理解為一個硬盤,S3提供了接口給你存取東西,安全,管理方便)。

大概的思路是,前端通過<input type="file"/>選擇文件,發送ajax請求到后端的controller,controller將請求的圖片數據進行大小裁剪、類型轉換后保存到本地指定的文件夾,同時將路徑返回,用於顯示圖片。

二,實踐

思路比較簡單,所以話不多說,直接上代碼:

前端代碼整合在react寫的一個圖片上傳組件里,image_uploader.js.jsx代碼如下

var ImageUploader = React.createClass({ getInitialState: function() { return { url: this.props.url }; }, onFileSelect: function(e) { var that = this; var files = e.target.files; if (files.length <= 0) { AlertModal.showWithProps("No file selected"); return; } var data = new FormData(); $.each(files, function(key, value) { data.append('file', value); data.append('type', that.props.type) }); this.upload(data); }, upload: function(data) { var that = this; if (!data) { return; } else { this.refs.filebtn.disabled = true; $("#loading-modal").modal('show'); $.ajax({ url: '/missions/upload_image', type: 'post', data: data, processData: false, contentType: false }).done(function(res){ console.log(res); that.setState({url: res.url}); }).fail(function(err){ console.log(err); AlertModal.showWithProps("Upload Failed"); }).always(function(){ $("#loading-modal").modal('hide'); that.refs.filebtn.disabled = false; }); } }, handleUrlChange: function(e) { this.setState({url: e.target.value}); }, render: function() { var form_input_name = this.props.model + "[thumb]"; var form_input_id = this.props.model+ "_thumb"; return ( <div className="image-uploader-inputs row"> <div className="col-sm-8 image-input"> <input className="form-control" name={form_input_name} id={form_input_id} ref="urlinput" value={this.state.url || ""} onChange={this.handleUrlChange}/> </div> <div className="btn btn-primary btn-file image-input-btn"> <input type="file" onChange={this.onFileSelect} ref="filebtn"/> </div> </div> ); } });
  • 效果圖

上面的重點在於upload函數,源碼是最好的文檔,如果看源碼需要太多注釋的話,那肯定是我寫的代碼質量還不夠高,請批評指出。

寫這個的時候遇到兩個問題:

  • 一,這個組件是用在_form.html.slim里的,這個表單是用於信息的錄入的,大家對表單應該比較熟悉,既然要用在表單里,就是給這個組件作標識,標明name和id,代碼片段如下(從上面的代碼中截取):
var form_input_name = this.props.model + "[thumb]"; var form_input_id = this.props.model+ "_thumb";
  • 1
  • 2
<input className="form-control" name={form_input_name} id={form_input_id} ref="urlinput" value={this.state.url || ""} onChange={this.handleUrlChange}/>
  • 1
  • 二,使用<input type="file"/>有一個普遍的問題,自帶的UI不美觀。 
    自帶的UI
    谷歌/百度“input file btn”會有許多解決方案,家里網速差就沒細看。我的做法是把這個btn設為透明,相關的代碼及css如下:
<div className="btn btn-primary btn-file image-input-btn"> <input type="file" onChange={this.onFileSelect} ref="filebtn"/> </div>
  • 1
  • 2
  • 3
.image-input-btn { float: left; width: 15%; background-image: image-url("upload.png"); background-size: 30px; background-position: center; background-repeat: no-repeat; input { //hide file input button width: inherit; opacity: 0; } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

接下來看看后端的代碼:

def upload_image # => will resize later image_relative_path = "/assets/images/#{params[:type]}/#{Time.now.to_i}.png" image_path = File.expand_path(File.dirname(__FILE__) + '/../..') + "/public" + image_relative_path data = File.read(params[:file].path) img = File.new(image_path, "w+") if img img.syswrite(data) end img.close render json: {url: image_relative_path} end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

代碼同樣簡單,構建文件路徑,保存文件,返回路徑。因為開發進度的原因這里並沒有對圖片的大小和類型進行修改(為了減少數據傳輸量,在前端進行大小的修改比較合理),后面review這部分代碼的時候會再更新這篇博客。

值得說說的是:

  • 圖片命名的問題,采用了時間戳,命名不會重復,為了方便管理,將不同類型的圖片存於不同的文件夾,但是只以時間戳命名可獲取的信息太少,不利於運營人員管理,后期會再仔細考慮這個問題。
  • 存放路徑問題,在后端代碼里,rails能將圖片存在rails項目文件夾的任何位置,但是客戶端顯示圖片的時候,只能訪問public文件夾里的內容,於是決定將圖片存在public文件夾下。

三,總結及思考

完成這個功能不需要太久,但代碼外的思考不少。圖片小,甚至能用Git備份圖片,也許不是長久之計,開始想念aws的好了,容災交給aws處理最好不過了,后面試了一下AWS S3

希望自己寫得越多,考慮得越遠。

在家的第十天,日子過得還是那么快,終於還是有點慌。接觸的東西越多,要學的就越多,興奮之余隱隱感覺時間不夠用。既然夢想着成為一名全棧工程師,就理應付出更多。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM