后端文件上传以及下载功能实现

简介: 上一章讲到前端文件下载功能的实现,之前也讲过前端文件上传功能的实现,这一章就讲一下后端怎么接收前端上传的文件,以及怎么实现文件下载功能。

上一章讲到前端文件下载功能的实现,之前也讲过前端文件上传功能的实现,这一章就讲一下后端怎么接收前端上传的文件,以及怎么实现文件下载功能。

往期文章

这里使用的技术栈为:nodejs + express + multer,如果你不熟悉这些技术栈,可以先去了解一下。

multer 相关的还没写过,但是很简单,就是调用几个
api,这篇文章中也会介绍使用方式,具体可以看看官方文档,传送门

一、项目结构

什么也没有,就一个app.js就够了,项目依赖的包也很少,就是expressmulter

app.js文件内容如下:

const express = require('express');

const app = express();

app.use(express.static(__dirname + '/public'));

app.listen(3000, () => {
   

});

然后在public目录下新建一个index.html文件,这个就是前端相关的内容了,内容如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>文件上传和文件下载</title>
</head>
<body>

<div>
  <h1>文件上传</h1>
  <input type="file" name="file">
  <input type="submit" value="上传" id="upload">
</div>

<hr/>

<div>
  <h1>文件下载</h1>
  <input type="button" value="下载" id="download">
</div>

<script>
  // 上传
  document.getElementById('upload').onclick = function () {
    
    var file = document.querySelector('input[type=file]').files[0];
    var formData = new FormData();
    formData.append('file', file);
    var xhr = new XMLHttpRequest();
    xhr.open('POST', '/upload');
    xhr.send(formData);
  };

  // 下载
  document.getElementById('download').onclick = function () {
    
    var xhr = new XMLHttpRequest();
    xhr.open('GET', '/download');
    xhr.send();
    xhr.responseType = 'blob';
    xhr.onload = function () {
    
      var blob = xhr.response;
      var a = document.createElement('a');
      a.href = URL.createObjectURL(blob);
      a.download = 'download.jpg';
      a.click();
    }
  }
</script>
</body>
</html>

这里没有使用file-type来判断文件类型,这里就是一个简单的文件上传和下载功能,如果你想要判断文件类型,可以自己去实现一下。

上的环境都准备好了,控制台输入node app.js,然后访问http://localhost:3000/index.html,如果可以看到你写的页面,那么就说明环境搭建成功了。

二、文件上传

前端就不讲了,可以参考之前的文章,上面也列出了代码。

使用nodejs来接收前端上传的文件,首先肯定是需要有一个接口来接收的,这里就是/upload接口,接口的代码如下:

// 引用multer
const multer = require('multer');

// 创建上传文件的中间件
const upload = multer().single('file');

// 上传文件的接口
app.post('/upload', upload, (req, res) => {
   
    res.send(req.file);
});

这里使用的是multer来接收前端上传的文件,multer是一个nodejs的中间件,用来处理multipart/form-data类型的表单数据,它主要用于上传文件,但是也可以用于其他用途。

multer 的使用

这里是multer的最简单的使用方式,上面multer().single('file')这个就是创建一个上传文件的中间件,single表示只接收一个文件,file表示前端上传文件的name属性值。

它还可以有其他的使用方式,比如:

// 接收多个文件
multer().array('file', 5);

// 接收任意数量的文件
multer().any();

// 接收任意数量的文件,但是限制文件的大小
multer({
   limits: {
   fileSize: 1024 * 1024}}).any();

上面的示例中看到了multer还可以限制文件的大小,这里的limits就是限制的配置,那就肯定还有其他的配置,比如:

  • dest 或者 storage:用来配置上传文件的存储路径,这个属性是一个函数,函数的参数有三个:
    • req:请求对象
    • file:上传的文件对象
    • cb:回调函数,用来配置上传文件的存储路径
  • fileFilter:用来配置上传文件的过滤器,这个属性是一个函数,函数的参数有三个:
    • req:请求对象
    • file:上传的文件对象
    • cb:回调函数,用来配置上传文件的过滤器
  • limits:用来配置上传文件的大小限制,这个属性是一个对象,里面有两个属性:
    • fieldNameSize:用来配置上传字段名称的大小限制,默认为100个字节
    • fieldSize:用来配置上传字段值的大小限制,默认为1MB
    • fields:用来配置上传字段非文件的数量限制,默认为Infinity
    • fileSize:用来配置上传文件的大小限制,默认为Infinity
    • files:用来配置上传文件的数量限制,默认为Infinity
    • parts:用来配置上传字段和文件的数量限制,默认为Infinity
    • headerPairs:用来配置上传字段和文件的数量限制,默认为2000
const options = {
   
    dest: (req, file, cb) => {
   
        // 配置上传文件的存储路径,这里需要自己创建一个文件夹
        cb(null, __dirname + 'public/uploads');
    },
    fileFilter: (req, file, cb) => {
   
        // 配置上传文件的过滤器
        cb(null, true);
    },
    limits: {
   
        fieldNameSize: 100,
        fieldSize: 1024 * 1024,
        fields: Infinity,
        fileSize: 1024 * 1024,
        files: Infinity,
        parts: Infinity,
        headerPairs: 2000
    }
};

const upload = multer(options).single('file');

multer 的进阶使用

你以为上面讲完配置,multer就这些功能?不,它还有更多的功能,比如:

1. 文件的存储方式

上面虽然讲到了dest 或者 storage可以配置上传文件的存储路径,但是它只能配置上传文件的存储路径,不能配置上传文件的存储方式,比如:

const options = {
   
    dest: (req, file, cb) => {
   
        // 配置上传文件的存储路径,这里需要自己创建一个文件夹
        cb(null, __dirname + 'public/uploads');
    }
};

const upload = multer(options).single('file');

这种方式配置出来的上传文件的存储方式是DiskStorage,也就是存储在硬盘上,如果你只是想接收上传的文件进行一些操作,或者不想存在硬盘上,那么这种方式就不合适。

那么怎么配置上传文件的存储方式呢?multer提供了两种存储方式:

  • DiskStorage:存储在硬盘上
  • MemoryStorage:存储在内存中
const options = {
   
    storage: multer.diskStorage({
   
        destination: (req, file, cb) => {
   
            // 配置上传文件的存储路径,这里需要自己创建一个文件夹
            cb(null, __dirname + '/public/uploads');
        },
        filename: (req, file, cb) => {
   
            // 配置上传文件的文件名
            cb(null, file.originalname);
        }
    })
};

const upload = multer(options).single('file');

这里也就补充了storage配置的使用方式,它是一个对象,需要使用multer.diskStorage或者multer.memoryStorage
来配置上传文件的存储方式,然后再配置destinationfilename来配置上传文件的存储路径和文件名。

multer.diskStoragemulter.memoryStorage都是函数,它们都接收一个对象作为参数,这个对象有两个属性:

  • destination:用来配置上传文件的存储路径
    • req:请求对象
    • file:上传的文件对象
    • cb:回调函数,用来配置上传文件的存储路径
  • filename:用来配置上传文件的文件名
    • req:请求对象
    • file:上传的文件对象
    • cb:回调函数,用来配置上传文件的文件名

这里的cb回调函数的第一个参数是error,如果配置出错,就需要传入error,否则传入null,第二个参数是配置的结果。

2. 文件的过滤器

上面讲到了fileFilter可以配置上传文件的过滤器,比如:

const options = {
   
    fileFilter: (req, file, cb) => {
   
        // 配置上传文件的过滤器
        cb(null, true);
    }
};

const upload = multer(options).single('file');

这个过滤器是用来过滤上传的文件的,比如只允许上传jpgpng格式的图片,那么就需要配置这个过滤器,它接收三个参数:

  • req:请求对象
  • file:上传的文件对象
  • cb:回调函数,用来配置上传文件的过滤器

获取上传的文件

上面讲到了如何配置上传文件,那么如何获取上传的文件呢?在multer中,它提供了一个single
方法,用来获取上传的文件,它接收一个参数,就是上传文件的name属性,比如:

const upload = multer().single('file');

这里的file就是上传文件的name属性,配置好了之后,他会将上传的文件保存到req.file中,比如:

const upload = multer().single('file');

app.post('/upload', upload, (req, res) => {
   
    console.log(req.file);
    res.send('上传成功');
});

这里的req.file就是上传的文件对象,它有以下属性:

  • fieldname:上传文件的name属性
  • originalname:上传文件的原始文件名
  • encoding:上传文件的编码
  • mimetype:上传文件的MIME类型
  • destination:上传文件的存储路径
  • filename:上传文件的文件名
  • path:上传文件的完整路径
  • size:上传文件的大小
  • buffer:上传文件的二进制数据
  • stream:上传文件的stream对象
  • field:上传文件的name属性

上传多个文件

上面讲到了如何上传单个文件,那么如何上传多个文件呢?在multer中,它提供了一个array方法,用来获取上传的多个文件,它接收两个参数,第一个参数是上传文件的name属性,第二个参数是上传文件的最大数量,比如:

const upload = multer().array('file', 5);

上面文件上传已经讲够了,更多的使用方式可以自行尝试,上传的文件multer保存都给你做好了,所以你只需要配置好上传的文件就可以了,接下来讲下载文件。

文件下载

文件下载很简单,相比于文件上传更简单,如果服务器存在这个文件可以直接下载,这个在我上面的配置中已经配置好了:

app.use(express.static(__dirname + '/public'));

就是这一句,它会将public目录下的文件作为静态资源,所以你可以直接访问public目录下的文件,然后前端就可以直接使用a标签下载了,比如:

<a href="/download/1.jpg" download="1.jpg">下载</a>

这种方式就不过多的讲了,接下来讲一下如何使用Node.js下载文件。

使用Node.js下载文件

直接使用express下载文件,需要使用res.download方法,比如:

app.get('/download', (req, res) => {
   
    const file = __dirname + '/public/1.jpg';
    res.download(file);
});

上面的代码就是使用Node.js下载文件的代码,它会将public目录下的1.jpg文件下载下来,这里的res.download方法是express提供的,它接收一个参数,就是文件的路径,它会自动的将文件下载下来,如果你想要自定义文件名,可以这样:

app.get('/download', (req, res) => {
   
    const file = __dirname + '/public/1.jpg';
    res.download(file, '2.jpg');
});

上面的代码就是将1.jpg文件下载下来,并且重命名为2.jpg,这里的重名并不是真正的重命名,它只是将文件的Content-Dispositionfilename属性设置为2.jpg,这个如果在a标签中设置download属性就失效了。

其他的下载方式

上面是使用了Express提供的res.download方法来下载文件,当然还有其他的方式可以下载文件,比如:

  • 使用fs模块的createReadStream方法来读取文件,然后使用res.write方法来写入文件,最后使用res.end方法来结束响应,这种方式比较麻烦,但是可以自定义响应头,比如:
app.get('/download', (req, res) => {
   
    const file = __dirname + '/public/1.jpg';
    const stream = fs.createReadStream(file);
    res.writeHead(200, {
   
        'Content-Type': 'application/octet-stream',
        'Content-Disposition': 'attachment; filename=1.jpg'
    });
    stream.pipe(res);
});

下载网络文件

上面的代码都是下载本地文件,如果你想要下载网络文件,可以使用http模块的get方法来获取文件,然后使用res.write方法来写入文件,最后使用res.end方法来结束响应,比如:

app.get('/download', (req, res) => {
   
    const http = require('http');
    const url = 'http://www.baidu.com/img/bd_logo1.png';
    http.get(url, (response: any) => {
   
        res.writeHead(200, {
   
            'Content-Type': 'application/octet-stream',
            'Content-Disposition': 'attachment; filename=1.jpg'
        });
        response.pipe(res);
    });
});

上面的代码就是下载百度的logo图片,这里的http.get方法接收两个参数,第一个参数是文件的地址,第二个参数是回调函数,回调函数接收一个参数,就是http模块的response对象,它是一个Readable流,所以可以使用pipe方法来将文件写入响应中。

总结

本文主要讲了如何使用Node.js下载文件,包括本地文件和网络文件,可以说覆盖面还是比较广的,总体来说还是比较简单的,哈哈哈。

目录
相关文章
|
6月前
|
前端开发
前端接受后端文件流并下载到本地的方法
前端接受后端文件流并下载到本地的方法
1469 0
|
1月前
|
存储 前端开发 Java
Java后端如何进行文件上传和下载 —— 本地版(文末配绝对能用的源码,超详细,超好用,一看就懂,博主在线解答) 文件如何预览和下载?(超简单教程)
本文详细介绍了在Java后端进行文件上传和下载的实现方法,包括文件上传保存到本地的完整流程、文件下载的代码实现,以及如何处理文件预览、下载大小限制和运行失败的问题,并提供了完整的代码示例。
453 1
|
5月前
|
存储 Java Maven
大事件后端项目31--------文件上传_阿里云OSS_入门程序
大事件后端项目31--------文件上传_阿里云OSS_入门程序
|
5月前
|
存储 运维 Java
大事件后端项目30------文件上传_阿里云OSS_准备工作
大事件后端项目30------文件上传_阿里云OSS_准备工作
|
5月前
|
存储 Java Spring
大事件后端项目29------文件上传_本地存储
大事件后端项目29------文件上传_本地存储
|
4月前
|
前端开发
支付系统--微信支付21--搭建前端环境,payment-demo-front这个项目文件夹是前端显示文件,payment-demo是后端项目,支付页面常见三个页面:购买课程,我的订单,下载账单
支付系统--微信支付21--搭建前端环境,payment-demo-front这个项目文件夹是前端显示文件,payment-demo是后端项目,支付页面常见三个页面:购买课程,我的订单,下载账单
|
5月前
|
存储 前端开发 Java
Spring第三课,Lombok工具包下载,对应图书管理系统列表和登录界面的后端代码,分层思想
Spring第三课,Lombok工具包下载,对应图书管理系统列表和登录界面的后端代码,分层思想
|
4月前
|
前端开发 数据库
网页设计,若依项目修改(网页设计,若依项目修改(It must be done)10------下载字典类型后端三句话在做啥
网页设计,若依项目修改(网页设计,若依项目修改(It must be done)10------下载字典类型后端三句话在做啥
|
5月前
|
对象存储
大事件后端项目32--------文件上传_阿里云OSS_程序集成
大事件后端项目32--------文件上传_阿里云OSS_程序集成
|
6月前
|
JavaScript 前端开发 关系型数据库
旅游规划助手:结合Vue的交云性设计和Python的强大后端功能
【4月更文挑战第11天】本文探讨了如何使用Vue.js和Python(Flask或Django)构建旅游规划助手应用,简化旅行规划。首先,确保安装了Python、Node.js、数据库系统和Git。接着,介绍如何用Python搭建后端API,分别展示了Flask和Django的例子。然后,利用Vue.js初始化前端项目,结合Vuex和Vue Router构建用户界面。最后,通过Axios实现前端与后端的数据通信。这样的架构有利于团队协作和代码维护,便于扩展应用功能。
79 2

热门文章

最新文章