zoukankan      html  css  js  c++  java
  • rails上载文件

    2.3.3  改进“新增留言”
    我们希望当新增留言的时候,允许用户上传图片,并能判断上传文件的类型是否为图片和文件是否过大。这在Rails中不难做到,不需要使用任何插件,只用十分简洁的代码即可实现图片的上传功能!这的确是一件让程序员愉快的事情。

    在这一节,我们来改进“新增留言”,着重介绍图片上传的实现。

    修改/app/views/message路径下的new.rhtml视图文件。修改后的代码如下:

    <table valign="top" width="100%"  border="0" cellspacing="0" cellpadding="0">

        <tr>

            <td>   

                <center>

                <%= error_messages_for 'message' %>

                </center>

                <!-- 将multipart选项设置为true,允许上传文件 -->

                <%= start_form_tag ({ :action => 'create', :id => @message }, :multipart => true) %>

                    <table align="center" width="400" border="0" cellpadding="0" cellspacing="0"

     bgcolor="#BFCAE6">

                        <tr>

                            <td colspan="2" id="title">新增留言</td>

                        </tr>  

                        <tr>

                            <td width="15%"><b>标题</b></td>

                            <td ><%= text_field('message', 'title', :size => "30")%></td>                                      

                        </tr>

                        <tr>

                            <td width="15%"><b>内容</b></td>

                            <td ><%= text_area 'message', 'detail', "cols" => 40, "rows" => 10 %></td>

                        </tr>

                        <tr>

                            <td width="15%"><b>贴图</b></td>

                            <!-- 调用file_field帮助方法,生成一个文件域 -->

                            <td ><%= file_field 'message', 'picture' %></td>

                        </tr>

                        <tr>

                            <td colspan="2" align="center"><%= submit_tag '提交' %></td>

                        </tr>

                    </table>

                <%= end_form_tag %>

            </td>

        </tr>

    </table>

    上面的代码在start_form_tag帮助方法中指定multipart的选项值为true,使得该表单能够发送文件数据。并且,通过调用file_field帮助方法,生成了一个文件域。这里的picture属性只是个虚拟属性,因为在数据库的messages表中并不存在这个属性。这需要我们对这个虚拟属性做一些处理,使之对应messages表中的真实属性。具体实现方式下面会有详细介绍。

    上面的表单是没有为留言时间设计表单域的,因为我们可以通过更简便的方式来为Message对象的这个属性赋值:messages表中表示留言时间的字段名为created_at,数据类型设计为timestamp,这样,当保存一条Message对象对应的记录时,Rails就会自动将当前时间赋值给created_at列,而不需要我们手动赋值。

    在message_controller.rb控制器文件中,需要修改create方法,修改后该方法的代码片段如下。

    def create

        # 查找出当前留言的User对象

        user=User.find(session[:user_id])

        # 将该User对象赋值给参数中Message对象的user属性

        params[:message][:user]=user

        # 构造一个Message对象,并使用message参数来初始化该对象

        @message = Message.new(params[:message])

        # 如果Message对象能成功保存进数据库

        if @message.save

            flash[:notice] = '新增留言成功!'

            # 重定向到list Action

            redirect_to :action => 'list'

        else

            # 提交new Action

            render :action => 'new'

        end

    end

    在create方法的定义中,前面两句代码是scaffold生成的默认代码中所没有的。这是因为user_id是messages表参照users表的外键列,scaffold不会自动生成对外键列的操作。所以,我们需要根据session[:user_id]来查找出留言的User对象,并把该对象赋值给表单参数中的Message对象,作为它的一个user属性。这样,当Message对象调用save方法保存进数据库的时候,会让该Messge对象对应的数据行参照到该User实例对应的数据行。

    在Message Model文件中,重定义一个picture=方法。因为我们的new.rhtml视图文件中有一个picture表单域,当提交表单后控制器将发送一个message[:picture]的请求参数,这个请求参数将要求Message类里包含一个picture=方法,该方法用于接受message[:picture]请求参数。

    picture=方法负责把message[:picture]请求参数(这个请求参数值是一个文件对象,里面包含了非常丰富的信息)解析出来。下面是picture=方法的代码:

    # 提供picture=方法,将一个picture的表单域设置成Message对象的多个属性

    def picture=(picture_field)

        transaction do       

            # 如果用户上传了图片

            if picture_field.size>0 then

                # @picture_size为上传图片的文件大小

                @picture_size=picture_field.size

                # @picture_type为上传图片的文件类型

                @picture_type=picture_field.content_type.chomp

                # 设置Message对象的picture_content_type属性

                self.picture_content_type =@picture_type

                 # 设置Message对象的picture_data属性

                self.picture_data = picture_field.read

            end

        end

    end

    提供了picture=方法之后,我们就将message[:picture]请求参数与messages表中的真实属性picture_content_type和picture_data对应起来了。

    在上传文件方面,Rails处理得很好,表单中的文件域参数值不再是一个简单的类型值,而是已经被包装成一个文件对象,它也有size,content_type和read方法,直接调用这些方法,即可返回这个文件对象的大小、文件类型和包含的二进制数据。

    当用户添加一条留言时,我们需要对留言对象进行模型校验,这可以通过在message.rb模型文件中重写validate方法来实现。代码如下:

    def validate

        # 验证title不能为空

        errors.add("", "标题不能为空") if title.empty?

        # 验证detail不能为空

        errors.add("", "内容不能为空") if detail.empty?

        # 下面校验上传的图片

        if @picture_type != nil

            # 校验上传图片的文件类型

            errors.add("", "贴图不是合法的图片文件") unless @picture_type =~ /^image/

        end

        if @picture_size != nil

            # 校验上传图片的文件大小

            errors.add("", "贴图文件太大,应不能超过50 KB") if @picture_size > MAX_IMAGE_SIZE

        end

    end

    在上面的代码中,我们校验留言标题、留言内容的值不能为空,上传的文件类型必须是图片形式,并且文件大小不能超过允许上传的最大图片值(MAX_IMAGE_SIZE为允许上传的最大图片值)。

  • 相关阅读:
    [enum]enum的用法
    gridview汇出EXCEL (ExportGridViewToExcel(dt, HttpContext.Current.Response);)
    c#用正则表达式判断字符串是否全是数字、小数点、正负号组成 Regex reg = new Regex(@"^(([0-9]+.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*.[0-9]+)|([0-9]*[1-9][0-9]*))$");
    GridView里的文本框改变事件
    转发 win7+iis7.5+asp.net下 CS0016: 未能写入输出文件“c:WindowsMicrosoft.NETFrameworkv2.0.50727Temporary ASP.NET Files 解决方案
    验证上转文件类型的正则表达式
    EXCEL设置选中单元格样式
    转发!HTML 复选框 checkbox 的 JavaScript 的全选和全反选
    dataGrid转换dataTable
    wince mobile环境下播放WAV声音
  • 原文地址:https://www.cnblogs.com/hannover/p/1381034.html
Copyright © 2011-2022 走看看