Rails 多文件上传

gh_ruby · 2022年04月24日 · 最后由 heroyct 回复于 2022年04月26日 · 326 次阅读

多文件上传

最近做了一个多文件上传的功能,由于对 rails 不太熟悉,没有找到好用的方法,就自己用 jquery 写了一个。各位有什么更好的解决方法可以交流交流😄


参考代码

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <script src="http://common.cnblogs.com/script/jquery.js" type="text/javascript"></script>
</head>
<body>
  <div class="attachment">
    <div class="attachment_file">
      <div class="new_file">
        <span class="file_name0">上传附件</span>
      </div>
      <div class="delete delete0" name="0" onclick="deleteAttachment(0)">删除</div>
      <div class="old_file">
        <input class="app_file0" type="file" name="0">
      </div>
    </div>
  </div>
  <div class="push_btn" onclick="appSubmit()">提交</div>
</body>
</html>
<style >
  .attachment_file{
    display: flex;
    width: 284px;
  }
  .new_file {
    display: inline;
    align-items: center;
    height: 35px;
    color: #1284da;
    width: 252px;
    overflow: hidden;
  }
  .new_file a{
    color: #1284da;
  }
  .old_file {
    position: absolute;
    height: 35px;
    width: 252px;
    opacity: 0;
  }
  .old_file input{
    width: 252px;
  }
  .delete {
    display: inline;
    align-items: center;
    height: 35px;
    color: #1284da;
    width: 40px;
    margin-left: 5px;
    visibility: hidden;
  }
  .push_btn {
    width: 120px;
    height: 40px;
    background-color: #d8d8d8;
    border: 1px solid #a4a4a4;
    border-radius: 5px;
    text-align: center;
    line-height: 40px;
    cursor: pointer;
  }
</style>
<script type="text/javascript" charset="utf-8">
  var attachment_num = 0;
  var attachment = {};

  // 文件操作
  $('.attachment').on('change', function (e) {
    let num = e.target.name
    if($(`.app_file${num}`)[0].files.length>0){
      let name = $(`.app_file${num}`)[0].files[0].name
      $(`.file_name${num}`).text(name)
      if(e.target.name == attachment_num){
        $(`.delete${attachment_num}`).css({"visibility":"visible"});
        attachment_num++
        var divObj = `<div class="attachment_file">
          <div class="new_file">
            <span class="file_name${attachment_num}" name="${attachment_num}">上传附件</span>
          </div>
          <div class="delete delete${attachment_num}" name="${attachment_num}"  onclick="deleteAttachment(${attachment_num})">删除</div>
          <div class="old_file">
            <input class="app_file${attachment_num}" type="file" name="${attachment_num}">
          </div>
        </div>`
        $(".attachment").append(divObj);
      }
      trimAttachment()
    }else{
      deleteAttachment(Number(num))
    }
  })

  // 删除附件
  function deleteAttachment(num){
    $(`.delete${num}`).parent().remove()
    for(let i = num+1; i <= attachment_num; i++){
      $(`.file_name${i}`).attr('name',`${i-1}`);
      $(`.file_name${i}`).attr('class',`file_name${i-1}`);

      $(`.delete${i}`).attr('name',`${i-1}`);
      $(`.delete${i}`).attr('onclick',`deleteAttachment(${i-1})`);
      $(`.delete${i}`).attr('class',`delete delete${i-1}`);

      $(`.app_file${i}`).attr('name',`${i-1}`);
      $(`.app_file${i}`).attr('class',`app_file${i-1}`);
    }
    attachment_num--
    trimAttachment()
  }

  // 整理附件
  function trimAttachment(){
    attachment = {};
    for(let i = 0; i < attachment_num; i++){
      files1 = $(`.app_file${i}`)[0].files[0];
      attachment[i] = files1
    }
    attachment["length"] = attachment_num
  }

  // 提交
  function appSubmit(){
    param = new FormData();
    for(var i = 0; i < attachment.length; i++){
      param.append(`attachment${i}`, attachment[i]);
    }
    param.append(`attachment_num`, attachment.length);

    $.ajax({
      method:"post",
      url:"/save",
      data: param,
      contentType: false,
      processData: false,
      success:function(data) {

      }
    })
  }

</script>

开发过程中的问题

  1. 本想通过 rails 中的 form.file_field 进行文件上传,但它的可操作性比较差,比如多个文件更换其中的几个文件很难实现
  2. 后来想通过给 input 赋值 FileList 的方式,查了一圈发现 FileList 不支持修改操作
  3. 最后只能通过定义变量,缓存需要上传的文件,结合 jquery 增加了删除修改的功能,然后提交时用 ajax 请求,FormData 传参

作为一名 ruby 新手,还望各位大佬多指教😆

这个跟 Rails 没什么太大关系吧。路子比较像前后端分离的,写这种应用比较建议 React,Vue 这些现代化框架,维护多文件会相对容易许多。JQuery 写这种会稍微烦一些,太多的 DOM 需要操作了。如果想集成到 Rails 生态,可以参考一下ActiveStorage里面的范例。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号