之前发布过一篇文章是关于文件上传的,但是虽然可以实现,但是存在一些需要优化的地方,这次讲一讲。
还是先上代码:
后端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提供的文件名称获取方法