Laravel 和 Vue.js 如何正确地处理文件上传?

Laravel

上传文件的方式

大多数如何使用 JavaScript 上传文件的文章实际上都在讲如何用 Base64 对文件内容编码,以便可以将其包含在 JSON 请求中。虽然可以用,但是效率不如其他方法。在本文中,我将展示如何在 Vue.js 和 axios 中使用multipart/FormData 方法上传文件。

JSON 中的 Base64

优点:

  • 不需要手动将数据编码/解码为 JSON 格式(如果使用任何前端框架或客户端库)
  • 文件的内容只是 JSON 对象中的另一个字段

缺点:

  • 需要在 Base64 中编码文件
  • 使用更多的 CPU,更多的内存以及占用更多的网络带宽(Base64 使用的空间比二进制文件多 33%)
  • 来自后端框架的支持很少

Multipart

优点:

  • 不需要用Base64编码文件
  • 使用更少的 CPU,更少的内存以及占用更少的网络带宽
  • 来自后端框架的全面支持

缺点:

  • 需要手动将数据编码/解码为 JSON 格式
  • 文件的内容与 JSON 对象是分开的

获取文件

无论哪种方式,您的页面都将具有一个文件输入组件,该文件输入组件使用户可以选择文件。如果您尝试在 Vue 上使用 v-model ,Vue 会报错,因为文件输入是只读的,因此我们通常为 change 事件添加事件处理程序。

<template>
    <input type="file" @change="selectFile">
</template>

<script>
    data: () => ({
        photo: null,
        description: '',
        productId: 0,
    }),

    methods: {
        selectFile(event) {
            // files 始终是数组,因为文件输入可能处于多种模式
            this.photo = event.target.files[0];
        }
    }
</script>

发送文件

文件输入元素具有 files 属性,该属性是 File 类实例的数组。它拥有所选文件的一些元数据以及读取其内容的方法。除此之外,它可以直接用作FormData 对象中的值。FormData 类允许使用 JavaScript 构造与普通 HTML 表单创建的相同请求。使用 axios,jQuery 或者普通的XMLHttpRequest 对象时,可以将 FormData 对象用作请求的主体。

以下几点:

const data = new FormData();
data.append('photo', this.photo);
data.append('description', this.description);
data.append('productId', this.productId);
axios.post("/api/photo", data);

大致相当于:

<form method="POST" enctype="multipart/form-data" action="/api/photo">
    <input type="file" name="photo"/>
    <input type="text" name="description"/>
    <input type="text" name="productId">
</form>

如果您将复杂数据作为数组或嵌套对象,则必须手动转换为 JSON:

const data = new FormData();
data.append('photo', this.photo);
const json = JSON.stringify({
    description: this.description,
    productId: this.productId,
});
data.append('data', json);
axios.post("/api/photo", data);

接收文件

在Laravel方面,完全支持使用 Request 类透明地处理文件上传。上载的文件是任何其他字段,框架将其作为 Illuminate\Http\UploadedFile 类的实例显示。从那里你可以读取文件的内容或将其存储在其他位置。

public function savePhoto(Request $request)
{
    // 验证(大小以 KB 为单位)
    $request->validate([
        'photo' => 'required|file|image|size:1024|dimensions:max_width=500,max_height=500',
    ]);

    // 读取文件内容
    $contents = file_get_contents($request->photo->path());

    // 或者只是将其移动到其他地方(例如:本地 storage 目录或 S3 )
    $newPath = $request->photo->store('photos', 's3');
}

如果你具有手动转换为JSON的复杂数据,则需要在使用前对其进行解码:

public function savePhoto(Request $request)
{
    $request['data'] = json_decode($request['data']);

    // 验证
    $request->validate([
        'data.description' => 'required|filled|size:100',
        'data.productId' => 'required|int|exists:App\Product,id'
    ]);

    // 其余和上面代码相同
}
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://dev.to/diogoko/file-upload-using...

译文地址:https://learnku.com/laravel/t/41701

本文为协同翻译文章,如您发现瑕疵请点击「改进」按钮提交优化建议
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!