Схема http-передачи файлов на основе nodejs играет важную роль в текущей разработке полного стека внешнего и внутреннего интерфейса.В этой статье я буду использовать несколько схем для реализации http-передачи больших файлов. Перед реализацией функции мы сначала пишем большой файл через fs-модуль nodejs и генерируем локальный файл в проекте:
const fs = require('fs');
const writeStream = fs.createWriteStream(__dirname + "/file.txt");
for(let i = 0;i <= 100000; i++) {
writeStream.write(`${i} —— 我是${i}号文件\n`, "utf-8");
}
writeStream.end();
После успешного выполнения приведенного выше кода создается файл размером3.2MBтекстовый файл большого размера, который будет служить «активом большого файла» для следующих схем. Прежде чем перечислять сценарии передачи больших файлов, давайте инкапсулируем два общедоступных метода, которые будут использоваться позже:文件读取方法
а также文件压缩方法
:
// 封装读取文件的方法
const readFile = async (paramsData) => {
return new Promise((resolve, reject) => {
fs.readFile(paramsData, (err, data) => {
if(err) {
reject('文件读取错误');
} else {
resolve(data);
}
})
})
}
// 封装文件压缩方法
const gzip = async (paramsData) => {
return new Promise((resolve, reject) => {
zlib.gzip(paramsData, (err, result) => {
if(err) {
reject('文件压缩错误');
} else {
resolve(result);
}
})
})
}
1. Передача через большие файлы после сжатия данных
Когда браузер отправляет запрос, он будет содержатьaccept
а также accept-*
Информация заголовка запроса используется для сообщения серверу типов файлов, поддерживаемых текущим браузером, списка поддерживаемых форматов сжатия и поддерживаемых языков. в заголовке запросаAccept-Encoding
Поле используется для указания серверу метода кодирования контента (обычно алгоритма сжатия), который может понять клиент. Сервер выберет метод, поддерживаемый клиентом, и передаст заголовок ответа.Content-Encoding
чтобы уведомить клиента о выборе, а заголовок ответа сообщает браузеру, что JS-скрипт, возвращенныйgzip
Алгоритм сжатия обработан
// 请求头
accept-encoding: gzip, deflate, br
// 响应头
cache-control: max-age=2592000
content-encoding: gzip
content-type: application/x-javascript
на основеAccept-Encoding
а также Content-Encoding
Чтобы понять поле, давайте проверим, что оно не включеноgzip
и включиgzip
Эффект.
// 实现一个简单的文件读取服务器(没有开启gzip)
const server = http.createServer(async (req, res) => {
res.writeHead(200, {
"Content-Type": "text/plain;charset=utf-8",
});
const buffer = await readFile(__dirname + '/file.txt');
res.write(buffer);
res.end();
})
server.listen(3000, () => {
console.log(`server启动成功`)
})
// 实现一个简单的文件读取服务器(开启gzip)
const server = http.createServer(async(req, res) => {
res.writeHead(200, {
"Content-Type": "text/plain;charset=utf-8",
"Content-Encoding": "gzip"
});
const buffer = await readFile(__dirname + '/file.txt');
const gzipData = await gzip(buffer);
res.write(gzipData);
res.end();
})
server.listen(3000, () => {
console.log(`server启动成功`)
})
2. Передача данных порциями
Декорации требуют большой HTML-таблицы, если генерируются данные, полученные из базы данных, или когда требуется большое количество картинок, их можно реализовать блокировкой.
Transfer-Encoding: chunked
Transfer-Encoding: gzip, chunked
заголовок ответаTransfer-Encoding
Значение поляchunked
, что указывает на то, что данные отправляются в виде серии фрагментов. должен быть в курсеTransfer-Encoding
а также Content-Length
Эти два поля являются взаимоисключающими, что означает, что эти два поля не могут одновременно появляться в ответном сообщении.
// 数据分块传输
const spilitChunks = async () =>{
const buffer = await readFile(__dirname + '/file.txt');
const lines = buffer.toString('utf-8').split('\n');
let [chunks, i, n] = [[], 0, lines.length];
while(i < n) {
chunks.push(lines.slice(i, i+= 10));
};
return chunks;
}
const server = http.createServer(async(req, res) => {
res.writeHead(200, {
"Content-Type": "text/plain;charset=utf-8",
"Transfer-Encoding": "chunked",
"Access-Control-Allow-Origin": "*",
});
const chunks = await spilitChunks();
for(let i =0; i< chunks.length; i++) {
setTimeout(() => {
let content = chunks[i].join("&");
res.write(`${content.length.toString(16)}\r\n${content}\r\n`);
}, i * 1000);
}
setTimeout(() => {
res.end();
}, chunks.length * 1000);
})
server.listen(3000, () => {
console.log(`server启动成功`)
})
2. Передача в виде потока данных
когда используешьNode.js
При возврате большого файла клиенту использование потока для возврата файлового потока позволяет избежать использования слишком большого объема памяти при обработке больших файлов. Конкретная реализация заключается в следующем. При возврате данных файла в виде потока заголовки ответа HTTPTransfer-Encoding
Значение поляchunked
, что указывает на то, что данные отправляются в виде серии фрагментов.
const server = http.createServer((req, res) => {
res.writeHead(200, {
"Content-Type": "text/plain;charset=utf-8",
"Content-Encoding": "gzip",
"Transfer-Encoding": "chunked"
});
fs.createReadStream(__dirname + "/file.txt")
.setEncoding("utf-8")
.pipe(zlib.createGzip())
.pipe(res);
})
server.listen(3000, () => {
console.log(`server启动成功`)
})