【Nest】文件下载——普通下载和流式下载
普通下载
直接对服务端中的某个路径进行响应下载。
import {
Controller,
Get,
Post,
Res,
UploadedFile,
UseInterceptors,
} from '@nestjs/common';
import { UploadService } from './upload.service';
import { FileInterceptor } from '@nestjs/platform-express';
import type { Response } from 'express';
import { join } from 'node:path';
import { zip } from 'compressing';
@Controller('upload')
export class UploadController {
constructor(private readonly uploadService: UploadService) {}
@Post('album')
@UseInterceptors(FileInterceptor('file')) // file 为前端表单字段名
uploadFile(@UploadedFile() file: Express.Multer.File) {
console.log(file);
return {
localPath: file.path,
onlinePath: 'http://localhost:3000/images/' + file.filename,
};
}
@Get('export')
downloadFile(@Res() res: Response) {
const url = join(__dirname, '../images/file-1741220280567-926338688.jpg');
res.download(url);
}
}
前端
<template>
<div>
<el-button @click="downloadFile">下载</el-button>
</div>
</template>
<script setup lang="ts">
const downloadFile = () => {
// 普通下载
window.open('/api/upload/export')
}
</script>
流式下载
import {
Controller,
Get,
Post,
Res,
UploadedFile,
UseInterceptors,
} from '@nestjs/common';
import { UploadService } from './upload.service';
import { FileInterceptor } from '@nestjs/platform-express';
import type { Response } from 'express';
import { join } from 'node:path';
import { zip } from 'compressing';
@Controller('upload')
export class UploadController {
constructor(private readonly uploadService: UploadService) {}
@Post('album')
@UseInterceptors(FileInterceptor('file')) // file 为前端表单字段名
uploadFile(@UploadedFile() file: Express.Multer.File) {
console.log(file);
return {
localPath: file.path,
onlinePath: 'http://localhost:3000/images/' + file.filename,
};
}
@Get('export')
downloadFile(@Res() res: Response) {
const url = join(__dirname, '../images/file-1741220280567-926338688.jpg');
res.download(url);
}
@Get('stream')
async downloadFileStream(@Res() res: Response) {
const url = join(__dirname, '../images/file-1741220280567-926338688.jpg');
const tarStream = new zip.Stream();
await tarStream.addEntry(url);
res.setHeader('Content-Type', 'application/octet-stream');
res.setHeader('Content-Disposition', `attachment; filename=heo`);
tarStream.pipe(res);
}
}
前端
<template>
<div>
<el-button @click="downloadFile">下载</el-button>
</div>
</template>
<script setup lang="ts">
/**
* 使用 Fetch API 异步获取指定 URL 的二进制数据,并触发下载
*
* @param {string} url - 要获取数据的 URL 地址
*/
const useFetch = async (url: string) => {
// 异步获取 URL 对应的二进制数据
const res = await fetch(url).then(res => res.arrayBuffer())
// 创建一个新的 <a> 元素
const a = document.createElement('a')
// 将获取到的二进制数据转换为 Blob 对象,并生成 URL
a.href = URL.createObjectURL(new Blob([res]))
// 设置下载的文件名
a.download = 'heo.zip'
// 触发 <a> 元素的点击事件,开始下载
a.click()
}
const downloadFile = () => {
// 流式下载
useFetch('/api/upload/stream')
// 普通下载
// window.open('/api/upload/export')
}
</script>