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

Laravel中无法将Azure流式响应存入ZipArchive问题求助

解决Laravel中Azure流式PDF存入ZipArchive的问题

你的问题核心在于Azure返回的流式响应未被正确转换为ZipArchive可识别的内容——直接返回响应时Laravel会自动处理流的输出,但手动存入压缩包时,需要显式读取流内容或重置流指针,否则ZipArchive会读取到空内容导致返回null。

核心原因

流式响应的Body指针可能已移至末尾(比如响应生成后做过调试、日志输出等操作),此时直接读取会得到空值;另外ZipArchive需要的是原始文件内容,而非响应对象本身。

解决方案(单个PDF存入)

方案1:直接读取流内容存入压缩包(适合小文件)

利用Laravel HTTP客户端的响应Body方法,重置指针后读取全部内容,再通过addFromString加入ZipArchive:

use Illuminate\Support\Facades\Http;

// 获取Azure流式PDF响应
$response = Http::withHeaders([
    'Authorization' => 'Bearer YOUR_AZURE_TOKEN', // 替换为Azure认证头
])->get('YOUR_AZURE_PDF_ENDPOINT', ['stream' => true]);

if (!$response->successful()) {
    abort(500, '获取PDF失败');
}

$zip = new ZipArchive();
$zipPath = storage_path('app/temp/single_pdf.zip');

if ($zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE)) {
    // 重置流指针到开头,确保读取全部内容
    $response->getBody()->rewind();
    $pdfContent = $response->getBody()->getContents();
    
    // 将PDF内容加入压缩包,指定文件名
    $zip->addFromString('document.pdf', $pdfContent);
    
    $zip->close();
    
    // 返回压缩包并自动删除临时文件
    return response()->download($zipPath)->deleteFileAfterSend(true);
}

abort(500, '创建压缩包失败');

方案2:通过临时文件存入(适合大文件,避免内存溢出)

将流式响应写入临时文件,再用addFile加入压缩包,处理完成后删除临时文件:

use Illuminate\Support\Facades\Http;

$response = Http::withHeaders([
    'Authorization' => 'Bearer YOUR_AZURE_TOKEN',
])->get('YOUR_AZURE_PDF_ENDPOINT', ['stream' => true]);

if (!$response->successful()) {
    abort(500, '获取PDF失败');
}

// 创建临时文件存储PDF内容
$tempFile = tempnam(sys_get_temp_dir(), 'azure_pdf_');
file_put_contents($tempFile, $response->getBody());

$zip = new ZipArchive();
$zipPath = storage_path('app/temp/single_pdf.zip');

if ($zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE)) {
    $zip->addFile($tempFile, 'document.pdf');
    $zip->close();
    
    // 清理临时文件
    unlink($tempFile);
    
    return response()->download($zipPath)->deleteFileAfterSend(true);
}

// 失败时清理临时文件
unlink($tempFile);
abort(500, '创建压缩包失败');

批量PDF存入扩展

只需循环处理每个Azure PDF请求,重复上述步骤逐个加入压缩包即可:

use Illuminate\Support\Facades\Http;

$pdfUrls = [
    'https://azure-endpoint/pdf1',
    'https://azure-endpoint/pdf2',
    // 更多PDF地址
];

$zip = new ZipArchive();
$zipPath = storage_path('app/temp/batch_pdf.zip');

if ($zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE)) {
    foreach ($pdfUrls as $index => $url) {
        $response = Http::withHeaders([
            'Authorization' => 'Bearer YOUR_AZURE_TOKEN',
        ])->get($url, ['stream' => true]);
        
        if (!$response->successful()) {
            $zip->close();
            abort(500, "第{$index+1}个PDF获取失败");
        }
        
        $response->getBody()->rewind();
        $pdfContent = $response->getBody()->getContents();
        $zip->addFromString("document_{$index+1}.pdf", $pdfContent);
    }
    
    $zip->close();
    return response()->download($zipPath)->deleteFileAfterSend(true);
}

abort(500, '创建压缩包失败');

关键注意事项

  • 每次读取流前必须调用rewind(),确保指针处于流的起始位置;
  • 大文件优先使用临时文件方案,避免内存占用过高;
  • 始终检查ZipArchive的open方法返回值,确保压缩包创建成功。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 19:09:24