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

JavaScript+Laravel实现大文件断点续传断网后fopen权限报错怎么解决

问题根因
  • 核心原因不是真的权限不足,而是Windows系统下多个请求同时写入同一个分片临时文件时,系统会给正在写入的文件加独占锁,后续请求再操作这个文件就会抛出权限拒绝错误。你正常网络下不会出现并发写同一个分片的情况,所以不会报错,断网重试时就会触发这个问题。
  • 前端配置testChunks: false关闭了分片存在性检测,断网恢复后续传时,已经上传过的分片会被重复上传,直接触发并发写冲突。
  • 断网时你只是弹出提示,没有暂停上传队列,resumable会按照你配置的重试规则不断发起请求,多个重试请求会同时请求同一个分片的写入接口。
修复方案

前端修改

  1. 开启分片检测,将resumable配置中的testChunks: false改为testChunks: true,resumable会在上传每个分片前先检测该分片是否已经上传成功,已成功的分片会直接跳过,避免重复写入。
  2. 优化断网处理逻辑,监听到网络断开时暂停上传,网络恢复后再继续:
resumable.on('fileProgress', function (file) { 
    if(navigator.onLine === true){
        updateProgress(Math.floor(file.progress() * 100));
        // 网络恢复后如果是暂停状态就重启上传
        if(resumable.isPaused()){
            resumable.upload()
        }
    }
    else{
        alert('网络已断开,上传暂停');
        // 暂停上传队列,避免无意义重试
        resumable.pause()
    }        
});
  1. 调整重试规则,仅针对网络错误类的响应重试,避免业务错误无意义重试:
resumable.on('fileError', function (file, response) { 
    console.log(response);
    // 如果是503类的服务端临时不可用错误再重试,其他错误可以终止上传给出提示
    if(response.status !== 503){
        alert('上传出错,请重新选择文件')
        resumable.cancel()
    }
});

后端修改

  1. 临时文件路径统一使用Laravel辅助函数生成,避免路径分隔符混乱。你当前报错路径中同时存在Windows的\\和Linux的/分隔符,可以在配置filesystems时统一用storage_path('app/products')生成路径。
  2. 增加文件写锁判断,接收分片时先检测文件是否被占用,如果被占用直接返回503让前端稍后重试:
public function uploadLargeFiles(Request $request) {
    $receiver = new FileReceiver('file', $request, HandlerFactory::classFromRequest($request));

    if (!$receiver->isUploaded()) {
        return response()->json(['status' => false, 'message' => '文件未上传'], 400);
    }

    try {
        $fileReceived = $receiver->receive();
    } catch (\ErrorException $e) {
        // 捕获文件打开失败的错误,返回503让前端重试
        if(str_contains($e->getMessage(), 'Permission denied') || str_contains($e->getMessage(), 'Failed to open stream')){
            return response()->json(['status' => false, 'message' => '临时文件占用'], 503);
        }
        throw $e;
    }

    if ($fileReceived->isFinished()) {
        $file = $fileReceived->getFile();
        $extension = $file->getClientOriginalExtension();
        $fileName = str_replace('.'.$extension, '', $file->getClientOriginalName());
        $fileName .= '_' . md5(time()) . '.' . $extension;

        $disk = Storage::disk(config('filesystems.default'));
        $path = $disk->putFileAs('products', $file, $fileName);

        unlink($file->getPathname());
        return [
            'path' => asset('storage/' . $path),
            'filename' => $fileName
        ];
    }

    $handler = $fileReceived->handler();
    return [
        'done' => $handler->getPercentageDone(),
        'status' => true
    ];
}

修改完成后可测试断网场景:上传一半断开网络,10秒后再恢复,验证是否可以正常续传完成。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 13:54:10