You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Laravel中将Vue上传的Blob文件正常存储到AWS S3?

如何在Laravel中正确存储前端上传的Blob文件?

我现在用Vue的文件上传插件通过API上传图片和PDF,这个插件支持上传时生成Blob字段,发送给Laravel的请求里能拿到Blob链接(浏览器可以正常访问),但后端用下面的代码存储时,保存的是64字节的损坏文件,不是原文件,请问怎么把Blob正常存到文件系统?

后端当前代码:

if ($request->has('files')) {
    $files = $request->get('files');
    $urls = [];
    foreach ($files as $file) {
        $filename = 'files/' . $file['name'];
        // Upload File to s3
        Storage::disk('s3')->put($filename, $file['blob']);
        Storage::disk('s3')->setVisibility($filename, 'public');
        $url = Storage::disk('s3')->url($filename);
        $urls[] = $url;
    }
    return response()->json(['urls' => $urls]);
}

问题根源

你碰到的核心问题是:前端传过来的blob字段其实是Blob对象的临时URL(格式类似blob:http://localhost:8080/xxxxxx),而不是文件的原始二进制数据或Base64编码内容。Laravel直接把这个URL字符串写入S3,自然只会生成几十字节的文本文件,而非你要上传的真实文件。

两种解决方案

方案1:后端通过Blob URL拉取真实文件内容(应急方案)

如果受限于插件逻辑,前端只能传Blob URL,你可以在后端通过这个URL请求获取真实的文件数据,再存储到S3:

if ($request->has('files')) {
    $files = $request->get('files');
    $urls = [];
    foreach ($files as $file) {
        // 从Blob URL获取文件二进制内容
        $fileContent = file_get_contents($file['blob']);
        if (!$fileContent) {
            // 处理获取失败的情况(比如跨域、URL过期)
            continue;
        }
        
        $filename = 'files/' . $file['name'];
        // 上传至S3
        Storage::disk('s3')->put($filename, $fileContent);
        Storage::disk('s3')->setVisibility($filename, 'public');
        $url = Storage::disk('s3')->url($filename);
        $urls[] = $url;
    }
    return response()->json(['urls' => $urls]);
}

注意:这种方式依赖后端服务器能访问到前端的Blob URL,如果前后端跨域或Blob URL已过期,会导致获取失败,且效率不如直接传文件。

方案2:前端改用FormData上传(推荐标准方案)

Web开发中文件上传的标准做法是用FormData传递文件,这样Laravel可以直接用原生的文件处理逻辑,完全规避Blob URL的问题:
Vue端示例代码:

// 假设file是你从插件中获取到的文件对象
const formData = new FormData();
// 支持多文件上传,用files[]作为键名
formData.append('files[]', file, file.name);

// 发送请求
axios.post('/your-upload-api', formData, {
    headers: {
        'Content-Type': 'multipart/form-data'
    }
});

后端对应调整代码:

if ($request->hasFile('files')) {
    $urls = [];
    foreach ($request->file('files') as $file) {
        if ($file->isValid()) {
            $filename = 'files/' . $file->getClientOriginalName();
            // 直接上传文件至S3
            $path = $file->storeAs('', $filename, 's3');
            Storage::disk('s3')->setVisibility($path, 'public');
            $url = Storage::disk('s3')->url($path);
            $urls[] = $url;
        }
    }
    return response()->json(['urls' => $urls]);
}

这种方式兼容性更强,上传效率更高,也不会出现跨域或URL失效的问题,是长期维护的最优选择。

总结

优先推荐使用FormData的标准上传方案;如果暂时无法修改前端逻辑,再用后端拉取Blob内容的应急方案,但要注意处理URL访问失败的异常情况。

内容的提问来源于stack exchange,提问作者Niraj Pandey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:16:52