使用Ruby on Rails进行HTML5文件拖放上传

时间:2012-10-08 01:44:22

标签: javascript ruby-on-rails ruby html5

在我的Ruby on Rails应用程序中,我有一个简单的文件上传按钮,我试图使用HTML5中的File / FileReader API替换为拖放框,具体使用this tutorial。我使用Ruby脚本将文件上传到我的public / data文件夹。我不确定如何将拖放脚本与其集成。我的想法是制作我已经隐藏的文件上传按钮,并在用户尝试提交时使用Javascript将其值设置为拖放图像的路径。

然而,当我尝试提交时,我收到错误:

  

文件名太长 - 公共/数据/数据:image / jpeg; base64,/ 9j / 4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP / sABFEdWNreQABAAQAAABkAAD / 4QMtaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNj ....

因为HTML5给出的临时文件存储名称太长了,我猜。

我尝试将字符串连接到前60个字符然后它给出了错误:

  

没有这样的文件或目录 - 公共/数据/数据:image / jpeg; base64,/ 9j / 4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAA

在任何情况下,该文件都不会添加到public/data文件夹中。

我的HTML:

<%= form_tag( { :action => 'create' }, :multipart => true ) %>
<div id="dropbox"><span id="droplabel">Drop file here...</span></div>
<img id="preview" alt="[ preview will display here ]" />

<%= hidden_field_tag :uploadfile, :id => "uploadfile", :name => "uploadfile" %>
<br /><br />
<div id="submit">
<%= submit_tag( "Upload file" ) %>
</div>

红宝石:

def create
    name = params[:uploadfile]
    directory = "public/data"
    path = File.join(directory, name)
    File.open(path, "wb") { |f| f.write(params[:uploadfile].read) }
     @project = Project.new({:filename => name, :location => path})

    respond_to do |format|
      if @project.save
        format.html { redirect_to @project, notice: 'Project was successfully created.' }
        format.json { render json: @project, status: :created, location: @project }
      else
        format.html { render action: "new" }
        format.json { render json: @project.errors, status: :unprocessable_entity }
      end
    end
  end

和JS:

$("#submit input").click(function() {
    $("#uploadfile").val($("#preview").attr("src"));
});

2 个答案:

答案 0 :(得分:0)

重点是使用params [:uploadfile]作为名称值是不必要的,如果你想要一个唯一的密钥,你可以使用SecureRandom.uuid

答案 1 :(得分:0)

问题看起来就像是将文件作为Base64编码的数据URL发送,这很好,但是当您向服务器发送POST时,文件名不会随之发生。您可能需要在将文件转换为数据URL之前提取文件名,以便将其与params中的文件一起发送。或者,像Madao建议的那样创建一个新的文件名(UUID)。

这至少应该解决你的文件名问题:

def create
    ##
    file = params[:uploadfile]
    name = params[:filename] || SecureRandom.uuid
    ##
    directory = "public/data"
    path = File.join(directory, name)
    File.open(path, "wb") { |f| f.write(file.read) }
    @project = Project.new({:filename => name, :location => path})

    respond_to do |format|
      if @project.save
        format.html { redirect_to @project, notice: 'Project was successfully created.' }
        format.json { render json: @project, status: :created, location: @project }
      else
        format.html { render action: "new" }
        format.json { render json: @project.errors, status: :unprocessable_entity }
      end
    end
  end