React & Expo - 如何上传和下载文件
介绍
我很难找到关于如何在基于 Expo 的移动应用程序中上传和下载文件的清晰示例。为了帮助面临同样挑战的其他人或任何只是好奇的人,我写了这篇文章。
在此过程中,我们将探索有助于理解的关键概念:
- 缓冲区
- 意图过滤器
- MIME 类型
- 应用程序/八位字节流
- 多部分/表单数据
- 还有更多...
我们将涵盖的内容:
- 使用 Fastify 服务器发送和接收文件。
- 在 React Web 应用程序上上传、下载和显示文件。
- 在 React Native (Expo) 移动应用上上传、下载和显示文件。
所有代码和Postman集合都可以在我的GitHub上找到。
服务器
服务器在Fastify(Express.js 的现代化版本)上运行。要启动应用程序,请执行以下操作:
- 使用终端导航到 /server
- 使用 npm install 安装依赖项
- 使用 npm run dev 运行服务器
在 app.js 中,我们有三个关键端点:
- 下载端点(/download)
fastify.get("/download", async function handler(_, reply) { const fd = await open(FILE_TO_DOWNLOAD); const stream = fd.createReadStream(); const mimeType = mime.lookup(FILE_TO_DOWNLOAD); console.log(`Downloading -> ${FILE_TO_DOWNLOAD}`); return reply .type(mimeType) .header( "Content-Disposition", `attachment; filename=${path.basename(FILE_TO_DOWNLOAD)}` ) .send(stream); });
此端点使用 createReadStream() 将 example.webp 作为流发送。包含 MIME 类型,以便客户端知道如何处理该文件。例如.webp,这将是image/webp。
?注意:MIME 类型定义了正在发送的文件的格式。这有助于客户端正确显示它。
查看更多 MIME 类型。
Content-Disposition 标头定义了如何将内容呈现给客户端。包括附件;文件名=;提示浏览器下载文件而不是内联显示它。要直接显示它,请使用内联而不是附件。
了解有关内容处置的更多信息
- 使用表单数据上传多个文件(/upload-multiples)
fastify.post("/upload-multiples", async function handler(request) { const parts = request.files(); const uploadResults = []; for await (const file of parts) { const fileBuffer = await file.toBuffer(); const filename = file.filename; const filePath = path.join(DIR_TO_UPLOAD, filename); await writeFile(filePath, fileBuffer); uploadResults.push({ filename, uploaded: true }); console.log(`Uploaded -> ${filePath}`); } return { uploadedFiles: uploadResults }; });
此端点接受多部分/表单数据请求。它:
- 从请求中检索文件。
- 将每个文件转换为缓冲区(二进制数据的 JavaScript 表示)。
- 将文件保存到 /upload 目录。
例如,请求可能如下所示:
- 使用八位字节流上传文件 (/upload-octet-stream)
fastify.get("/download", async function handler(_, reply) { const fd = await open(FILE_TO_DOWNLOAD); const stream = fd.createReadStream(); const mimeType = mime.lookup(FILE_TO_DOWNLOAD); console.log(`Downloading -> ${FILE_TO_DOWNLOAD}`); return reply .type(mimeType) .header( "Content-Disposition", `attachment; filename=${path.basename(FILE_TO_DOWNLOAD)}` ) .send(stream); });
此端点期望请求正文中有一个二进制文件(应用程序/八位字节流)。与multipart/form-data不同的是,该文件已经是二进制数据了,所以我们可以直接将其写入磁盘。
请求在 Postman 中看起来像这样:
网络(反应)
运行应用程序:
- 使用终端导航到 /web
- 使用 npm install 安装依赖项
- 使用 npm run dev 启动应用程序
Web 应用程序的所有功能都包含在 App.tsx 中:
这个 React 应用程序提供三个关键功能:
- 下载/显示文件
fastify.post("/upload-multiples", async function handler(request) { const parts = request.files(); const uploadResults = []; for await (const file of parts) { const fileBuffer = await file.toBuffer(); const filename = file.filename; const filePath = path.join(DIR_TO_UPLOAD, filename); await writeFile(filePath, fileBuffer); uploadResults.push({ filename, uploaded: true }); console.log(`Uploaded -> ${filePath}`); } return { uploadedFiles: uploadResults }; });
当用户单击“下载”按钮时,应用程序:
- 调用 /download 端点。
- 以二进制 blob 形式接收文件。
- 从 blob 创建一个 objectURL,充当浏览器可以访问的临时 URL。
行为取决于服务器返回的 Content-Disposition 标头:
- 如果 Content-Disposition 包含内联,则文件将显示在新选项卡中。
- 如果包含附件,则会自动下载该文件。
为了触发下载,应用程序会创建一个临时的 ; href 设置为 objectURL 的元素并以编程方式单击它,模拟用户下载操作。
- 使用表单数据上传文件
fastify.post("/upload-octet-stream", async function handler(request) { const filename = request.headers["x-file-name"] ?? "unknown.text"; const data = request.body; const filePath = path.join(DIR_TO_UPLOAD, filename); await writeFile(filePath, data); return { uploaded: true }; });
单击“上传文件”按钮时:
- uploadFile 函数运行,创建一个隐藏的 元素并模拟用户点击。
- 一旦用户选择一个或多个文件,这些文件就会附加到 FormData 对象。
- 请求被发送到 /upload-multiples 端点,该端点通过 multipart/form-data 接受文件。
这使得服务器能够正确处理和保存上传的文件。
- 使用八位字节流上传文件
const downloadFile = async () => { const response = await fetch(DOWNLOAD_API); if (!response.ok) throw new Error("Failed to download file"); const blob = await response.blob(); const contentDisposition = response.headers.get("Content-Disposition"); const isInline = contentDisposition?.split(";")[0] === "inline"; const filename = contentDisposition?.split("filename=")[1]; const url = window.URL.createObjectURL(blob); if (isInline) { window.open(url, "_blank"); } else { const a = document.createElement("a"); a.href = url; a.download = filename || "file.txt"; a.click(); } window.URL.revokeObjectURL(url); };
这种方法比使用 multipart/form-data 更简单 - 只需将文件作为二进制数据直接在请求正文中发送,并将文件名包含在请求标头中。
移动(世博会)
您可以使用以下命令启动应用程序:
- 导航到终端中的移动目录。
- 安装依赖项:npm install
- 使用 npm run android 或 npm run ios 运行项目
主要逻辑位于 App.tsx 中,它呈现以下内容:
fastify.get("/download", async function handler(_, reply) { const fd = await open(FILE_TO_DOWNLOAD); const stream = fd.createReadStream(); const mimeType = mime.lookup(FILE_TO_DOWNLOAD); console.log(`Downloading -> ${FILE_TO_DOWNLOAD}`); return reply .type(mimeType) .header( "Content-Disposition", `attachment; filename=${path.basename(FILE_TO_DOWNLOAD)}` ) .send(stream); });
要在新视图中显示文件(就像浏览器在新选项卡中打开文件一样),我们必须将响应作为 blob 读取,然后使用 FileReader 将其转换为 base64。
我们将文件写入缓存目录(只有应用程序可以访问的私有目录),然后使用 IntentLauncher 或共享(如果用户使用 iOS)显示它。
- 下载文件
fastify.post("/upload-multiples", async function handler(request) { const parts = request.files(); const uploadResults = []; for await (const file of parts) { const fileBuffer = await file.toBuffer(); const filename = file.filename; const filePath = path.join(DIR_TO_UPLOAD, filename); await writeFile(filePath, fileBuffer); uploadResults.push({ filename, uploaded: true }); console.log(`Uploaded -> ${filePath}`); } return { uploadedFiles: uploadResults }; });
这与 Web 进程类似,但我们必须使用 FileReader 将 blob 读取为 base64,然后请求权限将文件下载到用户想要保存文件的位置。
- 使用表单数据上传文件
fastify.post("/upload-octet-stream", async function handler(request) { const filename = request.headers["x-file-name"] ?? "unknown.text"; const data = request.body; const filePath = path.join(DIR_TO_UPLOAD, filename); await writeFile(filePath, data); return { uploaded: true }; });
使用 DocumentPicker 使用户能够选择文件,然后使用 FormData 将所选文件附加到请求中。过程非常简单。
- 将文件上传为八位字节流
const downloadFile = async () => { const response = await fetch(DOWNLOAD_API); if (!response.ok) throw new Error("Failed to download file"); const blob = await response.blob(); const contentDisposition = response.headers.get("Content-Disposition"); const isInline = contentDisposition?.split(";")[0] === "inline"; const filename = contentDisposition?.split("filename=")[1]; const url = window.URL.createObjectURL(blob); if (isInline) { window.open(url, "_blank"); } else { const a = document.createElement("a"); a.href = url; a.download = filename || "file.txt"; a.click(); } window.URL.revokeObjectURL(url); };
作为 Application/octet-stream 上传比使用 FormData 更简单:使用文件详细信息和内容类型设置标头,然后将文件添加到请求正文,就是这样!
结论
如何在平台之间查看、下载和上传文件可能有点令人困惑,在这篇文章中我们看到了最常见的。
希望对您有帮助?
让我在@twitter上
以上是React & Expo - 如何上传和下载文件的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

JavaScript是现代Web开发的基石,它的主要功能包括事件驱动编程、动态内容生成和异步编程。1)事件驱动编程允许网页根据用户操作动态变化。2)动态内容生成使得页面内容可以根据条件调整。3)异步编程确保用户界面不被阻塞。JavaScript广泛应用于网页交互、单页面应用和服务器端开发,极大地提升了用户体验和跨平台开发的灵活性。

JavaScript的最新趋势包括TypeScript的崛起、现代框架和库的流行以及WebAssembly的应用。未来前景涵盖更强大的类型系统、服务器端JavaScript的发展、人工智能和机器学习的扩展以及物联网和边缘计算的潜力。

不同JavaScript引擎在解析和执行JavaScript代码时,效果会有所不同,因为每个引擎的实现原理和优化策略各有差异。1.词法分析:将源码转换为词法单元。2.语法分析:生成抽象语法树。3.优化和编译:通过JIT编译器生成机器码。4.执行:运行机器码。V8引擎通过即时编译和隐藏类优化,SpiderMonkey使用类型推断系统,导致在相同代码上的性能表现不同。

Python更适合初学者,学习曲线平缓,语法简洁;JavaScript适合前端开发,学习曲线较陡,语法灵活。1.Python语法直观,适用于数据科学和后端开发。2.JavaScript灵活,广泛用于前端和服务器端编程。

JavaScript是现代Web开发的核心语言,因其多样性和灵活性而广泛应用。1)前端开发:通过DOM操作和现代框架(如React、Vue.js、Angular)构建动态网页和单页面应用。2)服务器端开发:Node.js利用非阻塞I/O模型处理高并发和实时应用。3)移动和桌面应用开发:通过ReactNative和Electron实现跨平台开发,提高开发效率。

本文展示了与许可证确保的后端的前端集成,并使用Next.js构建功能性Edtech SaaS应用程序。 前端获取用户权限以控制UI的可见性并确保API要求遵守角色库

我使用您的日常技术工具构建了功能性的多租户SaaS应用程序(一个Edtech应用程序),您可以做同样的事情。 首先,什么是多租户SaaS应用程序? 多租户SaaS应用程序可让您从唱歌中为多个客户提供服务

从C/C 转向JavaScript需要适应动态类型、垃圾回收和异步编程等特点。1)C/C 是静态类型语言,需手动管理内存,而JavaScript是动态类型,垃圾回收自动处理。2)C/C 需编译成机器码,JavaScript则为解释型语言。3)JavaScript引入闭包、原型链和Promise等概念,增强了灵活性和异步编程能力。
