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

FilePond结合Laravel从外部URL获取PDF文件异常问题排查

FilePond处理外部PDF链接时的文件损坏问题

问题背景

使用FilePond的fetch功能加载外部PDF链接时出现异常:

  • FilePond显示的文件大小远大于实际的2.3M
  • 使用PdfParser验证该PDF时出错,但本地上传同一文件完全正常
  • 怀疑是fetch过程中的Blob转换导致文件损坏

前端fetch代码

fetch: (source, load, error, progress, abort, headers) => {
    //progress(true, 0, 1024);
    axios({
        // headers: {'Access-Control-Expose-Headers': 'Content-Disposition'},
        method: 'get',
        url: 'fetch?url='+source,
        onUploadProgress: (e) => {
            // updating progress indicator
            progress(true, e.loaded, e.total);
        }
    }).then(response => {
        // passing the file id to Filepond
        if (response.status === 200) {
            let blob = new Blob([response.data],{
                type: "application/pdf"
            })
            load(blob)
        }

    }).catch((thrown) => {
        if (axios.isCancel(thrown)) {
            console.log('Request cancelled', thrown.message);
        } else {
            // handle error
            error(error)
            console.log(thrown)
        }
    })
},

Laravel后端端点代码

public function fetch(Request $request)
{
    $url = $request->url;
    
    $headers = [
        'Content-Type' => 'application/pdf',
    ];

    return response()->stream(function () use ($url) {
        $file = fopen($url, 'rb');
        fpassthru($file);
        fclose($file);
    }, 200, $headers);
}

load函数代码

load: (source, load, error, progress, abort, headers) => {
    // Should get a file object from the URL here
    // ...
    console.log(source)
    // Should call the progress method to update the progress to 100% before calling load
    // (computable, loadedSize, totalSize)
    //progress(true, 0, 1024);

    // Should call the load method with a file object when done
    load(source);

    // Should expose an abort method so the request can be cancelled
    return {
        abort: () => {
            // Let FilePond know the request has been cancelled
            abort();
        }
    };
},

排查与修复方案

1. 前端axios请求未正确处理二进制数据

axios默认会把响应解析为JSON格式,这会导致二进制PDF数据被错误转换为字符串,后续再转Blob就会损坏文件。

修改前端fetch代码:给axios添加responseType: 'blob'配置,直接获取Blob对象:

fetch: (source, load, error, progress, abort, headers) => {
    axios({
        method: 'get',
        url: 'fetch?url='+source,
        responseType: 'blob', // 关键配置:指定响应类型为blob
        onUploadProgress: (e) => {
            progress(true, e.loaded, e.total);
        }
    }).then(response => {
        if (response.status === 200) {
            // 直接使用响应返回的Blob,无需手动创建
            load(response.data)
        }
    }).catch((thrown) => {
        if (axios.isCancel(thrown)) {
            console.log('Request cancelled', thrown.message);
        } else {
            error(thrown.message) // 传递具体错误信息
            console.log(thrown)
        }
    })
},

2. 后端响应优化

当前后端使用stream返回文件流,可能存在未正确设置文件大小的问题,导致前端无法获取准确的文件总大小。可以修改后端代码,先获取文件内容和大小,再返回:

public function fetch(Request $request)
{
    $url = $request->url;
    
    // 获取文件内容和大小
    $fileContent = file_get_contents($url);
    $fileSize = strlen($fileContent);

    $headers = [
        'Content-Type' => 'application/pdf',
        'Content-Length' => $fileSize, // 添加文件大小头
    ];

    return response()->make($fileContent, 200, $headers);
}

注意:如果外部URL是远程地址,file_get_contents需要确保服务器允许访问该地址,可在php.ini中设置allow_url_fopen = On。

3. 完善load函数状态更新

当前load函数逻辑正确,但可以补充进度更新,确保FilePond能正确显示加载状态:

load: (source, load, error, progress, abort, headers) => {
    console.log(source)
    // 更新进度为100%
    progress(true, source.size, source.size);
    // 加载Blob对象
    load(source);

    return {
        abort: () => {
            abort();
        }
    };
},

验证修复

修改后重新测试:

  • 检查FilePond显示的文件大小是否与实际一致
  • 使用PdfParser验证加载后的PDF是否正常
  • 确认文件能正常预览或打开

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 22:10:02