From 49d836d3314ac2c3a445818e124b2f66d5908c64 Mon Sep 17 00:00:00 2001 From: guange <8863824@gmail.com> Date: Fri, 15 May 2015 23:47:22 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E5=A4=B4=E5=83=8F=E5=A4=A7?= =?UTF-8?q?=E5=B0=8F=E5=92=8C=E5=9B=BE=E7=89=87=E7=B1=BB=E5=9E=8B=E5=9C=A8?= =?UTF-8?q?=E5=90=8E=E5=8F=B0=E5=8A=A0=E5=85=A5=E9=99=90=E5=88=B6,?= =?UTF-8?q?=E4=B8=94=E9=80=9A=E8=BF=87=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/avatar_controller.rb | 68 ++++++++++++++------------ config/locales/en.yml | 1 + config/locales/zh.yml | 1 + lib/trustie/utils/image.rb | 28 ++++++++++- public/javascripts/jq-upload/upload.js | 15 ++++-- spec/requests/course_request_spec.rb | 42 +++++++++++++++- 6 files changed, 120 insertions(+), 35 deletions(-) diff --git a/app/controllers/avatar_controller.rb b/app/controllers/avatar_controller.rb index ef7cdf2f7..afd206c92 100644 --- a/app/controllers/avatar_controller.rb +++ b/app/controllers/avatar_controller.rb @@ -1,9 +1,9 @@ class AvatarController < ApplicationController - - + + include ActionView::Helpers::NumberHelper #before_filter :set_cache_buster include AvatarHelper - + def upload # Make sure that API users get used to set this content type # as it won't trigger Rails' automatic parsing of the request body for parameters @@ -29,43 +29,51 @@ class AvatarController < ApplicationController end if @temp_file && (@temp_file.size > 0) - diskfile=disk_filename(@source_type,@source_id) - @urlfile='/' << File.join("images","avatars",avatar_directory(@source_type),avatar_filename(@source_id,@image_file)) + if @temp_file.size > Setting.upload_avatar_max_size.to_i + @status = 1 + @msg = l(:error_upload_avatar_to_large, :max_size => number_to_human_size(Setting.upload_avatar_max_size.to_i)) + elsif Trustie::Utils::Image.new(@temp_file.tempfile.path).image? + diskfile=disk_filename(@source_type,@source_id) + @urlfile='/' << File.join("images","avatars",avatar_directory(@source_type),avatar_filename(@source_id,@image_file)) - # 用户头像上传时进行特别处理 - if @source_type == 'User' + # 用户头像上传时进行特别处理 + if @source_type == 'User' diskfile += "temp" @urlfile += "temp" - end - - logger.info("Saving avatar '#{diskfile}' (#{@temp_file.size} bytes)") - path = File.dirname(diskfile) - unless File.directory?(path) - FileUtils.mkdir_p(path) - end - md5 = Digest::MD5.new - File.open(diskfile, "wb") do |f| - if @temp_file.respond_to?(:read) - buffer = "" - while (buffer = @temp_file.read(8192)) - f.write(buffer) - md5.update(buffer) - end - else - f.write(@temp_file) - md5.update(@temp_file) end + + logger.info("Saving avatar '#{diskfile}' (#{@temp_file.size} bytes)") + path = File.dirname(diskfile) + unless File.directory?(path) + FileUtils.mkdir_p(path) + end + md5 = Digest::MD5.new + File.open(diskfile, "wb") do |f| + if @temp_file.respond_to?(:read) + buffer = "" + while (buffer = @temp_file.read(8192)) + f.write(buffer) + md5.update(buffer) + end + else + f.write(@temp_file) + md5.update(@temp_file) + end + end + + Trustie::Utils::Image.new(diskfile,true).compress(300) + @status = 0 + @msg = '' + else + @status = 2 + @msg = l(:not_valid_image_file) end -# self.digest = md5.hexdigest end @temp_file = nil - image = Trustie::Utils::Image.new(diskfile,true) - image.compress(300) - respond_to do |format| format.json{ - render :inline => "#{@urlfile.to_s}?#{Time.now.to_i}",:content_type => 'text/html' + render :inline => {status: @status, message:@msg, url:"#{@urlfile.to_s}?#{Time.now.to_i}"}.to_json,:content_type => 'text/html' return } format.js diff --git a/config/locales/en.yml b/config/locales/en.yml index 8989ae36a..844818ae4 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1521,4 +1521,5 @@ en: label_commit_failed: commit failed #api end error_upload_avatar_to_large: "too big (%{max_size})" + not_valid_image_file: not a valid image file diff --git a/config/locales/zh.yml b/config/locales/zh.yml index 5fcb1fb5c..a91faac0f 100644 --- a/config/locales/zh.yml +++ b/config/locales/zh.yml @@ -1984,3 +1984,4 @@ zh: label_code: 代码 error_upload_avatar_to_large: "超过大小限制 (%{max_size})" + not_valid_image_file: 不是有效的图片文件 diff --git a/lib/trustie/utils/image.rb b/lib/trustie/utils/image.rb index 9178b291a..f4ec328b3 100644 --- a/lib/trustie/utils/image.rb +++ b/lib/trustie/utils/image.rb @@ -3,11 +3,37 @@ module Trustie module Utils class Image - def initialize(file, bak) + def initialize(file, bak=false) @file = file @bak = bak end + def bitmap?(data) + data[0,2]==77.chr + 66.chr + end + + def gif?(data) + data[0,4]==71.chr + 73.chr + 70.chr + 56.chr + end + + def jpeg?(data) + data[0,4]== 0xff.chr + 0xd8.chr + 0xff.chr + 0xe0.chr + end + def png?(data) + data[0,2]==0x89.chr + 80.chr + end + + def image? + begin + f = File.open(@file,'rb') # rb means to read using binary + return false if f.size < 9 + data = f.read(9) # magic numbers are up to 9 bytes + return bitmap?(data) || gif?(data) || jpeg?(data) || png?(data) + ensure + f.close + end + end + def compress(size=300) backup if @bak begin diff --git a/public/javascripts/jq-upload/upload.js b/public/javascripts/jq-upload/upload.js index 985450648..71dbefc32 100644 --- a/public/javascripts/jq-upload/upload.js +++ b/public/javascripts/jq-upload/upload.js @@ -44,9 +44,18 @@ $(function() { }, done: function(e, data) { var imgSpan = jQuery('#avatar_image'); - imgSpan.attr({ - "src": data.result.text ? data.result.text() : data.result - }); + var result = data.result.text ? data.result.text() : data.result; + if(result){ + var o = JSON.parse(result); + if(o.status == 0){ + imgSpan.attr({ + "src": o.url + }); + } else { + alert(o.message); + } + } + } }); }); diff --git a/spec/requests/course_request_spec.rb b/spec/requests/course_request_spec.rb index d58df398e..99e4486b0 100644 --- a/spec/requests/course_request_spec.rb +++ b/spec/requests/course_request_spec.rb @@ -35,13 +35,53 @@ RSpec.describe "课程", :type => :request do context "修改课程图片" do include Rack::Test::Methods let(:avatar) {Rack::Test::UploadedFile.new("#{Rails.root}/spec/fixtures/test.jpg",'image/jpg')} + context "正常图片上传成功" do subject(:resp) {post upload_avatar_path(source_type: 'Course', source_id: course.id, format: :json),"avatar"=>{image: avatar}} it{ expect(subject).to be_ok } it{ expect(subject.body).not_to be_empty } + it "状态要为0" do + o = ActiveSupport::JSON.decode(subject.body) + expect(o["status"]).to eq(0) + end + it "要回传图片地址" do + o = ActiveSupport::JSON.decode(subject.body) + expect(o["url"]).not_to be_empty + end + end + + context "不是图片,上传失败" do + let(:invalid_avatar) {Rack::Test::UploadedFile.new("#{Rails.root}/spec/fixtures/hah.txt",'text/plain')} + before do + resp = post upload_avatar_path(source_type: 'Course', source_id: course.id, format: :json),"avatar"=>{image: invalid_avatar} + @o = ActiveSupport::JSON.decode(resp.body) + end + it "状态要为0" do + expect(@o["status"]).not_to eq(0) + end + it "要回传错误信息" do + expect(@o["message"]).to be_include("图片") + end + end + + context "文件过大,上传失败" do + before do + big_file = Rack::Test::UploadedFile.new("#{Rails.root}/spec/fixtures/test.jpg",'image/jpg') + allow(ActionDispatch::Http::UploadedFile).to receive(:new).and_return(double('BigFile',size: 10*1024*1024, original_filename: 'rais.jpg', tempfile: nil)) + # trace = TracePoint.new(:call) do |tp| + # p [tp.lineno, tp.defined_class, tp.method_id, tp.event] if tp.method_id == :post + # end + resp = post upload_avatar_path(source_type: 'Course', source_id: course.id, format: :json),'avatar[image]'=> big_file + @o = ActiveSupport::JSON.decode(resp.body) + end + it "状态要为0" do + expect(@o["status"]).not_to eq(0) + end + it "要回传错误信息" do + expect(@o["message"]).to be_include("大") + end end - it "不是图片,上传失败" end end