Rails 单图片上传与删除

学生图片上传(StudentPhoto)

  1. 在路由 routes.rb 添加上传方法 uploadFile
	resources :student_photos do
        member do
          # 上传图片
          post :uploadFile
        end
    end
  1. view -》 StudentPhoto -》form.html
    <div class="col-sm-3" style="margin-top: 20px;">
      <div class="img_border">
        <div class="img_plus">+</div>
        <div class="img_bt">点击上传</div>
        <canvas id="canvas" style="position:absolute;" class="form-group">
        </canvas>
        <%= file_field 'student','image',class: "upload", id: "file_btn" %>
      
<%= f.submit "提交", data:{:disable_with => '提交中...'}, :class => "base_bt"%>

css 图片框的样式

.img_border{
  position:relative;
  height: 200px;
  width:172px;
  border-radius: 10px;
  border:1px dashed rgba(197,208,219,1);
}
.img_plus{
  position:absolute;
  top:0;
  bottom: 0;
  margin: auto 0;
  width: 100%;
  text-align: center;
  font-size:50px;
  font-family:Microsoft YaHei;
  font-weight:400;
  color:rgba(197,208,219,1);
  display: flex;
  align-items: center;
  justify-content: center;
}
.img_bt{
  position:absolute ;
  bottom:0;
  font-size:16px;
  font-family:Microsoft YaHei;
  font-weight:300;
  color:rgba(255,255,255,1);
  background:rgba(153,153,153,1);
  height:24px;
  text-align: center;
  line-height:30px;
  border-bottom-left-radius: 5px;
  border-bottom-right-radius: 5px;
  width: 170px;
  height: 30px;
}
.upload{
  height: 200px;
  width: 170px;
  font-size: 100px;
  /* 设置透明度 */
  opacity: 0;
  filter:alpha(opacity=0);
  cursor:pointer;
}

script 部分代码

<script type="text/javascript">
  let file_btn = document.getElementById('file_btn');
  let canvas = document.getElementById('canvas');
  
  // 给定canvas在页面的占位,图片大于则宽高等比例缩小
  canvas.width = 170;
  canvas.height = 200;
  
  // 1.监听文件上传按钮的选择文件的事件
  file_btn.addEventListener("change", function () {
    let data_url = file_btn.files[0];
    console.log(data_url);
    
    // 2.使用FileReader类来读取文件内容
    let reader = new FileReader();
    reader.readAsDataURL(data_url);
    
    // 3.监听FileReader读取器读取完成事件(此事件后才可以获取到文件内容,进行图片渲染或上传)
    reader.onload = function () {
    
      // 3.1 异步渲染(canvas)
      let cxt = canvas.getContext('2d');
      let img = new Image();
      img.src = this.result;
      
      // 3.11 Image对象数据准备完成事件
      img.onload = function () {
        cxt.clearRect(0, 0, canvas.width, canvas.height);// 清空上一次的图片
        // 绘画
        let width = img.width;
        let height = img.height;
        let result = geometric_scaling(width, height, canvas.width, canvas.height);
        if (result['scale_by'] === 'none') {
            cxt.drawImage(img, (canvas.width - result['width']) / 2, (canvas.height - result['height']) / 2, result['width'], result['height'])
        }
        if (result['scale_by'] === 'width') {
            cxt.drawImage(img, 0, (canvas.height - result['height']) / 2, result['width'], result['height'])
        }
        if (result['scale_by'] === 'height') {
            cxt.drawImage(img, (canvas.width - result['width']) / 2, 0, result['width'], result['height'])
        }

      }
      
      // 3.2.异步上传(ajax) param = {"img":this.result}(数据格式为base64)
    }
  });
  
  // 封装等比缩小的方法
  function geometric_scaling(image_width, image_height, canvas_width, canvas_height) {
    let width = image_width;
    let height = image_height;
    let scale = 1;
    let scale_by = 'none';
    let return_data = {width, height, scale, scale_by};
    if (image_height < canvas_height && image_width < canvas_width) {
        return return_data
    } else if (image_height > canvas_height && image_width > canvas_width) {
    
        // 都大
        let scale_height = canvas_height / image_height;
        let scale_width = canvas_width / image_width;
        if (scale_height < scale_width) {
            scale = scale_height;
            scale_by = 'height';
        } else {
            scale = scale_width;
            scale_by = 'width';
        }
    }
    
    // 不是都小也不是都大的剩下两种情况
    else if (image_height > canvas_height) {
        scale = canvas_height / image_height;
        scale_by = 'height';
    } else {
        scale = canvas_width / image_width;
        scale_by = 'width';
    }
    return_data['width'] = image_width * scale;
    return_data['height'] = image_height * scale;
    return_data['scale'] = scale;
    return_data['scale_by'] = scale_by;
    return return_data
  }

</script>
  1. 在 student_photos_controller.rb ,添加 uploadFile 方法
    观看方法顺序:create -》uploadFile -》getFileName
    class StudentPhotosController < ApplicationController

      # 上传图片
      def uploadFile(file, id)
        if !file.original_filename.empty?
          # 生成一个文件名  随机+时间+格式
          # 路径:upload/student/ + 学生id + 文件名
          # mime = file.content_type
          # ext 为上传文件类型后缀
          ext = file.original_filename.split(".")[-1]  # .pop()
          @filename = getFileName(id, file.original_filename, ext)
          # 判断文件是否存在,不存在则创建一个以学号命名的文件夹
          afile = "#{Rails.root}/public/upload/student/#{id}"
          FileUtils.mkdir_p(afile) unless File.exists?(afile)

          # 向目录写入文件
          File.open(Rails.root.join(afile, @filename), "wb") do |f|
            f.write(file.read)
          end
          # 返回文件名称,保存到数据库中
          return @filename
        end
      end

      def getFileName(id, filename,ext)
        if !filename.nil?
          # 防止新文件名重复
          # 生成安全的base64字符串
          key = SecureRandom.urlsafe_base64
          # 'upload/student/'+ id.to_s + '/' +
          name = key.to_s + 't' + Time.now.strftime("%y%m%d%I%M%S") + '.' + ext.to_s
          filename.sub(/.*./, name)
        end
      end

      def new
        @student_photo = ::Student.new
      end

      def create
        @student_photo = ::Student.new(student_photo_params)
        if !params[:student]['image'].blank?
          uploadFile(params[:student]['image'],@student_photo.student_code)
        end
        
        if @student_photo.save
          flash[:notice] = "学生图片保存成功"
          redirect_to admin_student_student_photos_path
        else
          flash[:error] = @student_photo.errors.full_messages.uniq.join(', ')
          redirect_to new_admin_student_student_photo_path
        end
      end

      def update
       
      end

      private
      def find_student_id
        @student_photo = ::Student.find(params[:id])
      end

      def student_photo_params
        params.require(:student).permit(:student_code)
      end
      
    end

实现效果如下图片框:

Rails 单图片上传与删除_第1张图片

编辑学生图片(显示、上传与删除)

  1. 在路由 routes.rb 添加以下方法
    删除图片 delete_simple_student_photo
    显示图片 all_student_photo
	resources :student_photos do
        member do
          # 上传图片
          post :uploadFile
        end
        collection do
          # 删除单张图片
          post :delete_simple_student_photo
          # 获取学生人脸图片
          get :all_student_photo
        end
      end
  1. view -》 StudentPhoto -》edit.html
	<div class="pic" style="border: none;">
        <div class="img_border">
          <div class="img_plus">+</div>
          <canvas id="canvas" style="position:absolute;" class="form-group"></canvas>
          <%= file_field 'student', 'image', class: "upload", id: "file_btn" %>
        
<%= f.submit "提交", data: {:disable_with => '提交中...'}, :class => "base_bt" %>

script 部分代码

<script type="text/javascript">

    // 获取该学生所有照片的路径,并循环插入到相册中
    $.ajax({
        type: "GET",
        url: "/student_photos/all_student_photo?id=<%= @student_photo.student_code %>",
        dataType: "json",
        // 请求成功
        success: function (result) {
            // 取出图片地址的数组
            let pic_file = result.pic_file;
            for (i = 0; i < pic_file.length; i++) {
                  $("#pic_div").append("
+ i + "\" class=\"pic\" src=\"" + pic_file[i] + "\">" + "X
"
); <% else %> $("#pic_div").append("
+ i + "\" class=\"pic\" src=\"" + pic_file[i] + "\">" + "
"
); <% end %> console.log(pic_file[i]) } }, // 请求失败,包含具体的错误信息 error: function (e) { console.log(e.status); console.log(e.responseText); alert("照片墙加载失败,请与管理员联系"); } }); function delImg(msg){ var m = confirm("确定删除该照片?") if(m == true){ $.ajax({ type: "POST", url: "/student_photos/delete_simple_student_photo", data: {msg: msg}, dataType: "json", // 请求成功 success: function (result) { let del = result.pic alert(del) history.go(0) }, // 请求失败,包含具体的错误信息 error: function (e) { console.log(e.status); console.log(e.responseText); alert("删除图片失败,请与管理员联系"); } }); }else{ alert("删除图片失败,请与管理员联系") } } let file_btn = document.getElementById('file_btn'); let canvas = document.getElementById('canvas'); // let pic = document.getElementById('pic'); // 给定canvas在页面的占位,图片大于则宽高等比例缩小 canvas.width = 170; canvas.height = 200; file_btn.addEventListener("change", function () { let data_url = file_btn.files[0]; console.log(data_url); // 2.使用FileReader类来读取文件内容 let reader = new FileReader(); reader.readAsDataURL(data_url); // 3.监听FileReader读取器读取完成事件(此事件后才可以获取到文件内容,进行图片渲染或上传) reader.onload = function () { // 3.1 异步渲染(canvas) let cxt = canvas.getContext('2d'); let img = new Image(); img.src = this.result; // 3.11 Image对象数据准备完成事件 img.onload = function () { cxt.clearRect(0, 0, canvas.width, canvas.height);// 清空上一次的图片 // 绘画 let width = img.width; let height = img.height; let result = geometric_scaling(width, height, canvas.width, canvas.height); if (result['scale_by'] === 'none') { cxt.drawImage(img, (canvas.width - result['width']) / 2, (canvas.height - result['height']) / 2, result['width'], result['height']) } if (result['scale_by'] === 'width') { cxt.drawImage(img, 0, (canvas.height - result['height']) / 2, result['width'], result['height']) } if (result['scale_by'] === 'height') { cxt.drawImage(img, (canvas.width - result['width']) / 2, 0, result['width'], result['height']) } } // 3.2.异步上传(ajax) param = {"img":this.result}(数据格式为base64) } }); // 封装等比缩小的方法 function geometric_scaling(image_width, image_height, canvas_width, canvas_height) { let width = image_width; let height = image_height; let scale = 1; let scale_by = 'none'; let return_data = {width, height, scale, scale_by}; if (image_height < canvas_height && image_width < canvas_width) { return return_data } else if (image_height > canvas_height && image_width > canvas_width) { // 都大 let scale_height = canvas_height / image_height; let scale_width = canvas_width / image_width; if (scale_height < scale_width) { scale = scale_height; scale_by = 'height'; } else { scale = scale_width; scale_by = 'width'; } } // 不是都小也不是都大的剩下两种情况 else if (image_height > canvas_height) { scale = canvas_height / image_height; scale_by = 'height'; } else { scale = canvas_width / image_width; scale_by = 'width'; } return_data['width'] = image_width * scale; return_data['height'] = image_height * scale; return_data['scale'] = scale; return_data['scale_by'] = scale_by; return return_data } </script>

css 图片显示和删除按钮样式

  .pic_list{
    width: 100%;
    height: 100%;
    padding-bottom: 0%;
    position: relative;
    overflow: hidden;
  }
  .delImg {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: gray;
    color: white;
    position: absolute;
    right: 12px;
    top: 12px;
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: .9 ;
    cursor: pointer;
  }
  .delImg:hover{
    background: red;
    color: white;
    opacity: .9;
  }
  1. 在 student_photos_controller.rb ,添加显示与删除图片方法
class StudentPhotosController < ApplicationController
		
	   # 显示学生全部图片
      def all_student_photo
        file_path = "/upload/student/#{params[:id]}"
        pic_file = []
        if File.directory?("#{Rails.root}/public#{file_path}")
          Dir.foreach("#{Rails.root}/public#{file_path}") do |filename|
            # ruby遍历目录下所有文件时会包含“.”和“..”,这两者都属于目录,需要进行排除
            unless File.directory?(filename)
              pic_file << "#{file_path}" + '/' + filename
            end
          end
        end
        render json: {pic_file: pic_file}
      end

	  #删除单张图片
      def delete_simple_student_photo
        msg = params[:msg]
        File.delete("#{Rails.root}/public/#{msg}")
        pic = "该图片删除成功"
        render json: {pic: pic}
      end
      
      # 上传图片
      def uploadFile(file, id)
        if !file.original_filename.empty?
          # 生成一个文件名  随机+时间+格式
          # 路径:upload/student/ + 学生id + 文件名
          # mime = file.content_type
          # ext 为上传文件类型后缀
          ext = file.original_filename.split(".")[-1]  # .pop()
          @filename = getFileName(id, file.original_filename, ext)
          # 判断文件是否存在,不存在则创建一个以学号命名的文件夹
          afile = "#{Rails.root}/public/upload/student/#{id}"
          FileUtils.mkdir_p(afile) unless File.exists?(afile)

          # 向目录写入文件
          File.open(Rails.root.join(afile, @filename), "wb") do |f|
            f.write(file.read)
          end
          # 返回文件名称,保存到数据库中
          return @filename
        end
      end

      def getFileName(id, filename,ext)
        if !filename.nil?
          # 防止新文件名重复
          # 生成安全的base64字符串
          key = SecureRandom.urlsafe_base64
          # 'upload/student/'+ id.to_s + '/' +
          name = key.to_s + 't' + Time.now.strftime("%y%m%d%I%M%S") + '.' + ext.to_s
          filename.sub(/.*./, name)
        end
      end

      def new
        @student_photo = ::Student.new
      end

      def create
        @student_photo = ::Student.new(student_photo_params)
        if !params[:student]['image'].blank?
          uploadFile(params[:student]['image'],@student_photo.student_code)
        end
        
        if @student_photo.save
          flash[:notice] = "学生图片保存成功"
          redirect_to admin_student_student_photos_path
        else
          flash[:error] = @student_photo.errors.full_messages.uniq.join(', ')
          redirect_to new_admin_student_student_photo_path
        end
      end

      def update
       @student_photo = ::Student.find(params[:id])
        if !params[:student]['image'].blank?
          file_name = uploadFile(params[:student]['image'],@student_photo.student_code)
        end
        
        if @student_photo.update(student_photo_params)
          flash[:notice] = "学生图片修改成功"
          redirect_to edit_admin_student_student_photo_path(@student_photo)
        else
          flash[:error] = @student_photo.errors.full_messages.uniq.join(', ')
          redirect_to edit_admin_student_student_photo_path(@student_photo)
        end
      end

      private
      def find_student_id
        @student_photo = ::Student.find(params[:id])
      end

      def student_photo_params
        params.require(:student).permit(:student_code)
      end
      
    end

实现效果:

Rails 单图片上传与删除_第2张图片

这里主要介绍图片功能的实现,其他不重要的就跳过了。

你可能感兴趣的:(Ruby,on,Rails学习日志)