ajax上传、下载文件
一、上传
1.上传数据的封装
在上传文件时,最常用的方式是使用 FormData 对象,它会自动将请求头中的 Content-Type 请求头指定为multipart/form-data
服务端
在所有分片上传完毕后,服务器端会收到所有分片并合并。服务器可以根据 filename 和 chunkIndex 来识别每个分片,并按顺序合并它们。
const fs = require("fs");
const path = require("path");
const express = require("express");
const app = express();
const uploadDir = "uploads/"; // 保存分片的临时目录
app.post("/upload-chunk", (req, res) => {
const { filename, chunkIndex, totalChunks } = req.body;
const chunk = req.files.file; // 获取上传的分片文件
// 将每个分片存储到临时文件夹
const chunkPath = path.join(uploadDir, `${filename}.part${chunkIndex}`);
fs.writeFileSync(chunkPath, chunk.data);
// 检查是否所有分片都上传完成
if (parseInt(chunkIndex) === totalChunks - 1) {
// 合并所有分片
const filePath = path.join(uploadDir, filename);
const writeStream = fs.createWriteStream(filePath);
for (let i = 0; i < totalChunks; i++) {
const partPath = path.join(uploadDir, `${filename}.part${i}`);
const data = fs.readFileSync(partPath);
writeStream.write(data);
fs.unlinkSync(partPath); // 删除已合并的分片
}
writeStream.end();
res.send("文件上传成功并合并完成!");
} else {
res.send("分片上传成功!");
}
});
app.listen(3000, () => {
console.log("Server started on http://localhost:3000");
});
二、下载
服务端配置:
- 推荐:http响应成文件流,需要做如下响应头配置:
| Content-Disposition: attachment; filename="file.ext" | 指定下载文件的名称 |
| Content-Type: application/octet-stream | 通用二进制文件(适用于任意类型文件) |
- 不推荐:以json格式返回:将文件内容编码成base64,放入json的一个字段
前端接收数据方式:
-
文件流:
1. 使用 <a> 标签的 download 属性
这是实现文件下载最简单的方式。<a> 标签的 download 属性可以强制浏览器下载文件而不是直接打开文件。
<a href="path/to/file.pdf" download="filename.pdf">下载文件</a>
Blob 对象,并生成一个 URL 来进行下载。使用 Blob 和 URL.createObjectURL 生成下载链接
function downloadBlob(data, filename, mimeType) {
const blob = new Blob([data], { type: mimeType });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url); // 释放 URL
}
// 使用示例
const data = "Hello, this is a text file!";
downloadBlob(data, "example.txt", "text/plain");
2.使用ajax和 Blob 实现文件下载
不推荐使用该方法。下载速度比方法1要慢,要等ajax接收完文件再调用浏览器的文件保存api,文件较大时点击后可能需要很长时间才有反应,并且下载传输过程中出现问题后,无法断点续传。
async function downloadFile(url, filename) {
const response = await fetch(url);
const blob = await response.blob();
const a = document.createElement("a");
a.href = URL.createObjectURL(blob);
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(a.href);
}
// 使用示例
downloadFile("path/to/file.pdf", "downloaded_file.pdf");
-
json格式(后端把文件内容放入json中的某个字段,文件内容是base64编码)
function downloadFile() { fetch("/files/downloadJson?filename=example.pdf") .then(response => response.json()) .then(data => { if (!data.fileData) { console.error("文件数据为空"); return; } // 将 Base64 转换成 Blob const byteCharacters = atob(data.fileData); // 解码 Base64 const byteArrays = []; for (let i = 0; i < byteCharacters.length; i++) { byteArrays.push(byteCharacters.charCodeAt(i)); } const byteArray = new Uint8Array(byteArrays); const blob = new Blob([byteArray], { type: data.fileType }); // 创建下载链接 const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = data.fileName; // 设置下载的文件名 document.body.appendChild(a); a.click(); URL.revokeObjectURL(url); }) .catch(error => console.error("下载失败:", error)); }

浙公网安备 33010602011771号