• 表单上传文件 nodejs express Vue (优化)


    表单文件上传

    之前发布过一篇文章是关于文件上传的,但是虽然可以实现,但是存在一些需要优化的地方,这次讲一讲。

    还是先上代码:

    后端nodejs+express:

    在根目录下新建文件server.js

    var express = require('express');
    var app = express();
    var fs = require("fs");
    
    var bodyParser = require('body-parser');
    var multer  = require('multer');
    const path = require('path');
    
    app.use(express.static('public'));
    app.use(bodyParser.urlencoded({ extended: false }));
    app.use(multer({ dest: '/tmp/'}).array('image'));
    
    app.all('*', function(req, res, next) {
        res.header("Access-Control-Allow-Origin", "*");
        res.header("Access-Control-Allow-Headers", "X-Requested-With");
        res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
        res.header("X-Powered-By", ' 3.2.1');
        res.header("Content-Type", "application/json;charset=utf-8");
        next();
    });
    
    app.post('/file_upload', function (req, res) {
        console.log("req")
        console.log(req)
       console.log(req.files[0]);  // 上传的文件信息
       console.log(req.body.username);  //对应用户的username 使得上传的文件唯一
       
       req.files[0].originalname=req.body.username+req.files[0].originalname;//修改上传文件名
       var des_file = __dirname + "/static/upload/" + req.files[0].originalname;
       fs.readFile( req.files[0].path, function (err, data) {
            fs.writeFile(des_file, data, function (err) {
             if( err ){
                  console.log( err );
             }else{
                   res.writeHead(200,{'Content-Type':'text/html;charset=utf-8'});//设置response编码为utf-8
                //    response ={message:'File uploaded successfully', filename:req.files[0].originalname,des_file:des_file};                           
                   response =des_file;
                //    return "redirect:/#/";
                          }
              console.log( response );
              res.end( JSON.stringify( response ) );
    
           });
       });
    })
    
    
    var server = app.listen(8081, function () {
    
      var host = server.address().address
      var port = server.address().port
    
      console.log("应用实例,访问地址为 http://%s:%s", host, port)
    
    })

    前端vue代码:

    <template>
      <div class="hello">
        <h1>核酸检测报告上传</h1>
    <form action="http://127.0.0.1:8081/file_upload" method="post" enctype="multipart/form-data" target="nm_iframe" >
    <!-- <p>文件请命名为:核酸检测报告</p> -->
    <input type="file" name="image" id="f" size="50" />
    <br />
    <!-- 重命名: -->
    <input type="text" name="username" v-model="username"   >
    <!-- <p>{{username}}</p> -->
    <button type="submit" name="nm_submit" @click="getinfo" >上传文件</button>
    </form>
      <iframe id="id_iframe" name="nm_iframe" hidden >  </iframe>
    
    
    <a :href="fileurl" target="_block">下载附件</a>
    
    </div>
    </template>
    
    <script>
    import axios from 'axios'
    
    export default {
      name: 'HelloWorld',
      data () {
        return {
          msg: 'Welcome to Your Vue.js App',
          username:"",
          filename:"",
          fileurl:""
        }
      },
      mounted(){
      },
       methods: {    
         
        getinfo(){
          this.$message.success("文件上传成功!")
           var f = document.getElementById("f").files;
            alert(f[0].name);  
            console.log(f[0])
            this.filename=f[0].name
            this.fileurl="上传文件的地址为:"+'../../static/upload/'+this.username+this.filename
            console.log(this.fileurl)
        }
         }
       }
      
    </script>
    
    <!-- Add "scoped" attribute to limit CSS to this component only -->
    <style scoped>
    h1, h2 {
      font-weight: normal;
    }
    ul {
      list-style-type: none;
      padding: 0;
    }
    li {
      display: inline-block;
      margin: 0 10px;
    }
    a {
      color: #42b983;
    }
    </style>

    由于form表单提交后,页面会自动跳转到action所对应的地址,为了让表单提交且页面不跳转,我通过添加一个iframe控件的方法实现,

    原理就是,action跳转的页面直接展示在iframe中,这样父页面就不会进行跳转。

    之后还遇到遇到一个问题就是,由于是iframe空间获取返回值,所以对于取到form表单的返回值就变得十分困难,由于iframe相当于另外一个页面,所以当尝试获取iframe页面中的值的时候,会出现跨域的问题(后台服务启动在8081端口,vue页面启动在8080端口)

    解决办法:由于我们的返回值是文件的名字和地址,那么我们就可以直接在文件提交时,获取到文件的信息,通过

     var f = document.getElementById("f").files;  
    18         //上次修改时间  
    19         alert(f[0].lastModifiedDate);  
    20         //名称  
    21         alert(f[0].name);  
    22         //大小 字节  
    23         alert(f[0].size);  
    24         //类型  
    25         alert(f[0].type); 

    我们就可以获取所上传文件的所有信息。 这样就不需要抓取后台的返回值。

    这样我所需要的上传文件的地址和名称我就都解决了。这个问题也是通过各种学习,花费了2天的时间才解决,希望可以帮助到有需要的人。

    这里再提供一些关于文件的其他方法:

    判断文件类型

    var type=(src.substr(src.lastIndexOf("."))).toLowerCase();
    32 if(type!=".jpg"&&type!=".gif"&&type!=".jpeg"&& type!=".png"){
    33 alert("您上传图片的类型不符合(.jpg|.jpeg|.gif|.png)!");
    34 return false;
    35 }

    利用image属性来获取input file里文件的大小:

    <script type="text/javascript"> 
    function getFilePath(filePath)
    {
    var image=new Image();
    image.dynsrc=filePath;
    alert(image.filePath);
    }
    </</SPAN>script> 
    <body> 
    <INPUT TYPE="file" NAME="file" SIZE="30" onchange="getFileSize(this)"> 
    </</SPAN>body> 
    <script type="text/javascript">
    function getFileSize(fileObj)
    {
    var image=new Image();
    image.dynsrc=fileObj.value;
    alert(image.fileSize || fileObj.files[0].fileSize);
    }
    <script>
    <body>
    <INPUT TYPE="file" NAME="file" SIZE="30" onchange="getFileSize(this.value)">
    <body>

    这里感谢@ghfjj提供的文件名称获取方法

  • 相关阅读:
    AngularJS学习之旅
    webbug3.0菜鸟笔记1
    CTF练习(1)这是一张单纯的图片?
    三步删除U深度,老毛桃,大白菜捆绑软件!!
    flex弹性布局学习总结
    C# 播放音乐
    获取文件夹中的所有文件名
    C# 利用委托和事件 传入一个参数进行进行计算并返回结果
    C# 自定义颜色
    检测键盘是否按下指定按键
  • 原文地址:https://www.cnblogs.com/yqPhare/p/15958157.html
Copyright © 2020-2023  润新知