日常记录,Upload大家都懂,写接口接Upload大家也都会,但是别拦我,我说说我遇到的antd Design的Upload


假如我有个文件要上传到服务器并且返回文件保存的路径,那我可能会像下面这么写

FormData对象用以将数据编译成键值对,以便用XMLHttpRequest来发送数据。其主要用于发送表单数据,但亦可用于发送带键数据(keyed data)
而独立于表单使用。如果表单enctype属性设为multipart/form-data ,则会使用表单的submit()方法来发送数据,从而,发送数据具有同样形式。

前端代码,也就是你点击上传或者发送或者什么的之后执行的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
handleUpload = () => {
//为文件创建formData,key是files
const formData = new FormData();
fileList.forEach((file) => {
formData.append('files', file);
});

this.setState({
uploading: true,
});

reqwest({
url: '/upload',
method: 'post',
processData: false,
data: formData,
success: (resp) => {
console.log(resp)
this.setState({
fileList: [],
uploading: false,
});
message.success('upload successfully.');
},
error: () => {
this.setState({
uploading: false,
});
message.error('upload failed.');
},
});
}

接口,比较简陋,主要是看看直接接收会出来什么东西

1
2
3
4
5
6
7
8
let upload = multer({dest:'./目录/我的路径'}); //设置文件存储位置
app.use(express.static('./目录')); //设置静态文件目录
app.post("/upload",upload.single('files'),(req, res) => {
console.log(req.file)
const initFileName=req.file.originalname //原始文件名
console.log(initFileName)
res.send('./uploads/' + initFileName)
})

然后我选择一个叫测试.doc的文档上传。接着打开浏览器调试看看给我返回了什么

response
response

返回的文件地址,文件名是一串uuid的编码,开始我以为是组件默认的加密之后,但是服务器打印出来的文件信息显示encoding是“7bit”,所以并不是它默认加密或者什么
服务器打印
服务器打印

(虽然是uuid编码,但是两个图文件名为啥不一样。。。这个怪我这个爪,是因为服务器的时候我又拖了个文件上传,其实同一个文件的话,它是一样的)
当然你想直接console.log(formData)查看数据是不可以的,formData不允许,只允许类似这样的操作
1
2
3
4
5
let formData = new FormData()
formData.append('user', 'hhardyy')
获取 formData.get('user')
删除 formData.delete('user')
打印出来看的话就是 console.log(formData.get('user'))

假如怀疑是不是真的上传有文件的话,可以看看我们发的请求

服务器打印
服务器打印

实际上不仅是路径上的文件名变成了uuid编码,保存的文件名字也是一样
formData的信息
formData的信息

这时候如果想让保存的文件名字是上传时候的名字或者自定义名字的话可以这么操作,上面那个后台接收其实用的是Express4.x的中间件multer,它有个东西叫diskstorage,可以用来自定义存储位
置和自定义文件名
1
2
3
4
5
6
7
8
9
10
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, '文件存储目录')
},
filename: function (req, file, cb) {
cb(null, '文件名')
}
})

var upload = multer({ storage: storage })

安装 multer

1
npm install multer --save

destination和filename函数的参数req在这里.body都是空对象{},未装载formdata的文本域数据。file虽然装载了文件对象,但是信息不全。
接口可以改成这么写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './我的路径');
},//指定存储路径
filename: function (req, file, cb) {
//originalname=原始文件名,原始文件名是测试.doc,我把它后缀干掉,下面改成文件名+上传时间+文件后缀
let fileName=file.originalname.substring(0,file.originalname.indexOf('.',0))
cb(null, fileName + '-' + Date.now() + '.doc');//指定文件名和扩展名
}
});//指定存储方法,upload.single=单个文件,upload.Array=多个文件
app.use(express.static('./我的路径')); //设置静态文件目录
let upload = multer({ storage: storage }); //存储方法,5是限制大小,files是前端的files,一定要是一样的
app.use(upload.single('files', 5));
app.post('/upload', function (req, res) {
res.send('./路径' + req.file.filename); //文件的下载地址
console.log(req.file)
});

这样就正常了。继续深入了解可以去了解一下multer,这只是个简单的demo

保存的文件
保存的文件

还有一个问题就是返回的文件路径我想让别人点击一下就可以访问,那我这时候会用一个a来包裹,然后返回给前端直接可以点链接访问到文件的连接,但是后台返回的是字符串,你到前端的时候显示也是字符串,就像
这样

1
<a href="http://${this.state.fileAddress}">请点击查看我的简历</a>

其实在做react项目时,有时候需要将后台传过来的html元素的字符串形式变成真正的dom渲染到页面,如果直接插入的话页面显示的就是这段字符串,它不会自己进行转义,这时候可以在你要渲染的元素那写上

1
<span dangerouslySetInnerHTML={{__html: xxx}}></span>               // xxx是你的那段字符串,只是html元素会被转义成dom

语法是这样

1
2
let str="<a href="https://hhardyy.com/">hhardyy</a>"
<span dangerouslySetInnerHTML={{__html: str}}><span/>

今晚正好做了简历点对点发送接收功能,顺便写一写demo。