怎么实现 域名+ 文件名 + 图片名 来访问文件?

1,455 阅读4分钟

最近遇到这么一个需求(也就是题目所示),简单记录一下吧

现在来详细介绍一下要实现怎么样的一个需求,前端上传一张图片,后端获取到并存储在某个文件夹中,前端则能通过 http://127.0.0.1:3000/images/1632830606327.jpg (例子)来获取到后端的那张图片

具体效果如下:

image.png

我们用原生JS + 原生node 来实现这一需求

前端

先简单写个上传图片的demo

        <input type="file" id="abc" accept="image/jpeg,image/jpg,image/png">
        <button onclick="submited()">上传</button>
        <br/>
        <img src="" alt="" id="showImg" width="350"> //用于图片展示

这一步操作咱们就不做过多解释了,直接进入下一步,之后可想而知获取到上传的图片信息,这里通过文件读取器FileReader来读取文件,将其转化为base64格式(关于FileReader可以参考这一篇文章 FileReader API

        let file = document.getElementById('abc').files[0];
        let showImg = document.getElementById('showImg')
        let reader = new FileReader();
        if (file) {
            reader.readAsDataURL(file);
            reader.onload = function () {
                console.log(reader.result); //返回的是转成base64格式后的图片
            }
        }

处理完基本数据之后就是发起接口请求了

        function submited() {//button上面的那个方法
            let file = document.getElementById('abc').files[0];
            let showImg = document.getElementById('showImg')
            let reader = new FileReader();
            if (file) {
                reader.readAsDataURL(file);
                reader.onload = function () {
                    // console.log(reader.result);
                    //新加入的代码   发起接口请求
                    let baseImg = reader.result.replace(/^data:image\/\w+;base64,/,"");//去除掉前面的前缀
                    let xhr = new XMLHttpRequest();//原生js发起接口请求
                    xhr.open('post', 'http://127.0.0.1:3000/showImg');//用post发起请求
                    xhr.send(baseImg);//将数据也传给后端
                    xhr.onreadystatechange = function () {//注册事件
                        if (xhr.readyState == 4 && xhr.status == 200) {
                            //showImg.src = xhr.responseText; //将处理好的url赋值给img标签的src在页面展示
                        }
                    }
                }
            }
        }

前端基本到这就结束了,总结一下前端干了些啥:通过FileReader获取本地上传的图片,然后通过readAsDataURL(blob)方法将图片转化成base64格式,最后用原生JS发起接口请求

后端

接下来我们来处理后端的一些逻辑:通过http去启动一个3000端口的服务,再运用Buffer(关于Buffer)去解析处理前端传过来的图片信息,之后通过node含有的fs模块去解析下载通过Buffer处理后的数据(返回的一个Buffer实例)

先启动一个3000端口的服务

        let http = require('http');
        let server = http.createServer((req, res) => {
            
        });
        server.listen(3000, () => {
            console.log('服务已启动');
        })

然后再到createServer中去做之后的逻辑操作,前端后端启动的端口不一样,会产生跨域

        res.writeHead(200, {
            'Content-Type': 'text/plain',//设置请求头类型
            "Access-Control-Allow-Origin": "*"//*表示允许所有的域来请求  简单粗暴一点 实际操作不能这么操作
        })

前端发起的是对 /showImg 接口进行请求,而且我们发起的是post请求

        if (req.url == '/showImg' && req.method == 'POST') {
            let data = '';//存储前端传过来的数据
            req.on('data', cur => {
                data += cur;//post请求,数据会分段传输
            })
            req.on('end', () => {//数据接收完毕后调用
                //setPic(data,res); 这是后面的数据解析操作
            })
        }

后端的文件格式如下

image.png

我们将传过来的数据转化后下载到images中

        function setPic(data,res) {
            const path_1 = './images/' + Date.now() + '.jpg';//通过时间戳给图片重命名
            const picture = path_1.replace(/\./, 'http://127.0.0.1:3000');//这是返回给前端的信息
            const dataBuffer = Buffer.from(data, 'base64');//返回一个初始化的新的 Buffer 实例  
            fs.writeFile(path_1, dataBuffer, function (err) {//下载图片到images文件中
                if (err) {
                    res.end(err)
                }
            });
            res.end(picture);
        }

image.png 一些基本的逻辑就差不多实现了,前端传图片,后端获取重命名并下载。之后就是我们的关键步骤,我是这么干的,当识别到有接口请求时,就调用该函数去匹配url,如果url中含有存储图片的文件名则继续执行

    server.on('request',(req,res)=>{
            if(req.url.match(/\/images/)){//相当于将images文件暴露出来
                    fs.readFile('.' + req.url,(err,data)=>{
                            if(err){
                                    console.log(err);
                            }else{
                                    res.end(data);
                            }
                    })
            }
    })

至此已经完成了所有逻辑,现在可以通过http://127.0.0.1:3000/images/图片名 来访问图片

image.png

写在后面

这里是对于原生node而言,而对于express及koa就更方便了,只需要设置一个静态文件管理就行了

express

        const path = require('path')
        const express = require('express');
        app.use('/images',express.static(path.join(__dirname, 'images')));;//自带  托管静态文件
        app.listen(3000,() => {
            console.log('服务已启动');
        })

koa

通过 npm i koa-static 或者 yarn add koa-static 安装这个插件

        const Koa = require('koa')
        const app = new Koa()
        app.use(require('koa-static')(__dirname + '/images'))//托管静态文件

在我看来这三种其实都差不多,都是通过将静态文件夹暴露出来,供访问。