Deno 是一个新兴的 JavaScript 运行时环境,它提供了一种更加现代化的方式来编写服务器端应用程序。在 Deno 应用中,文件上传是一个常见的需求,本文将介绍如何在 Deno 应用中进行文件上传的最佳实践。
使用第三方库
在 Deno 应用中进行文件上传,我们可以使用一些第三方库来简化这个过程。其中最常用的库是 form-data
,它是一个用于构建 multipart/form-data 请求体的库,可以轻松实现文件上传功能。
// javascriptcn.com 代码示例 import { FormData } from 'https://deno.land/x/formdata/mod.ts'; const formData = new FormData(); formData.append('file', await Deno.readFile('path/to/file')); const response = await fetch('http://example.com/upload', { method: 'POST', body: formData, });
使用 form-data
库可以轻松地构建出包含文件上传的请求,但是需要注意的是,form-data
库并不是 Deno 内置的库,需要使用 deno.land/x
这样的第三方模块才能使用。
手动实现文件上传
除了使用第三方库之外,我们也可以手动实现文件上传。具体来说,我们需要通过 Deno.listen
方法创建一个 HTTP 服务器,然后在服务器的回调函数中处理文件上传请求。
// javascriptcn.com 代码示例 import { serve } from 'https://deno.land/std/http/server.ts'; const server = serve({ port: 8000 }); for await (const req of server) { if (req.method === 'POST' && req.url === '/upload') { const body = new Uint8Array(await Deno.readAll(req.body)); const boundary = getBoundary(req.headers.get('Content-Type') || ''); const parts = parseMultipart(body, boundary); for (const part of parts) { if (part.isFile) { await Deno.writeFile(part.filename, part.data); } } req.respond({ status: 200 }); } } function getBoundary(contentType: string): string { const match = /boundary=(.+)$/.exec(contentType); return match ? match[1] : ''; } function parseMultipart(body: Uint8Array, boundary: string): Part[] { const parts: Part[] = []; const boundaryDelimiter = new TextEncoder().encode(`--${boundary}\r\n`); const boundaryEndDelimiter = new TextEncoder().encode(`--${boundary}--\r\n`); let i = 0; while (i < body.length) { const delimiterIndex = body.indexOf(boundaryDelimiter, i); if (delimiterIndex === -1) { break; } const partStartIndex = delimiterIndex + boundaryDelimiter.length; const partEndIndex = body.indexOf(boundaryDelimiter, partStartIndex); if (partEndIndex === -1) { break; } const headerEndIndex = body.indexOf('\r\n\r\n', partStartIndex); if (headerEndIndex === -1) { break; } const headers = parseHeaders(body.slice(partStartIndex, headerEndIndex)); const contentStartIndex = headerEndIndex + 4; const contentEndIndex = partEndIndex - 2; const part: Part = { headers, data: body.slice(contentStartIndex, contentEndIndex), isFile: false, filename: '', }; if (part.headers['Content-Disposition']) { const match = /filename="(.+)"$/.exec(part.headers['Content-Disposition']); if (match) { part.isFile = true; part.filename = match[1]; } } parts.push(part); i = partEndIndex + boundaryDelimiter.length; } return parts; } function parseHeaders(headers: Uint8Array): Record<string, string> { const lines = new TextDecoder().decode(headers).split('\r\n'); const result: Record<string, string> = {}; for (const line of lines) { const [key, value] = line.split(': '); result[key] = value; } return result; } interface Part { headers: Record<string, string>; data: Uint8Array; isFile: boolean; filename: string; }
这段代码会创建一个 HTTP 服务器,并监听 8000 端口。当有文件上传请求到达时,它会解析请求体中的 multipart/form-data 数据,并将文件保存到磁盘上。需要注意的是,这段代码并不是最完整、最健壮的实现,但是足够说明手动实现文件上传的基本原理。
总结
在 Deno 应用中进行文件上传,我们可以使用第三方库来简化这个过程,也可以手动实现文件上传。无论哪种方式,都需要注意文件上传安全问题,避免上传恶意文件或者将文件保存到不安全的位置。希望本文能够帮助你更好地进行 Deno 应用开发。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6571e1bad2f5e1655daa97ea