Laravel无依赖上传Azure Blob Storage报错:Content-Length格式无效
问题排查与解决
错误原因
创建AppendBlob的PUT请求中,Content-Length头被设置为2,不符合Azure Blob Storage的要求。创建AppendBlob时,请求不应该包含任何请求体,对应的Content-Length必须为0。你的代码调用Http::put($createUri)时,Laravel HTTP客户端自动添加了默认内容或隐藏字符,导致Content-Length异常。
修复步骤
1. 修正创建AppendBlob的请求
修改创建逻辑,明确传递空请求体并强制设置Content-Length: 0:
$createResponse = Http::withHeaders([ 'x-ms-blob-type' => 'AppendBlob', 'x-ms-date' => gmdate('D, d M Y H:i:s T'), 'x-ms-version' => $version, 'Content-Length' => '0', // 明确指定Content-Length为0 ])->put($createUri, ''); // 传递空字符串作为请求体
2. 验证SAS Token权限
确保你的SAS Token包含以下权限:
c(Create):用于创建AppendBloba(Append):用于追加内容
缺少任一权限都会导致操作失败。
3. 可选:简化存在性检查逻辑
Azure Blob操作支持幂等性,可直接尝试创建Blob,若返回409 Conflict则说明Blob已存在,跳过创建步骤即可,省去额外HEAD请求:
try { $createResponse = Http::withHeaders([ 'x-ms-blob-type' => 'AppendBlob', 'x-ms-date' => gmdate('D, d M Y H:i:s T'), 'x-ms-version' => $version, 'Content-Length' => '0', ])->put($createUri, ''); } catch (\Illuminate\Http\Client\RequestException $e) { // 仅当错误不是Blob已存在时抛出异常 if ($e->response->status() !== 409) { throw new \Exception('Failed to create new blob: ' . $e->response->body()); } }
完整修复后的函数代码
private static function output($path, $text): bool { $accountName = config('filesystems.disks.azure.account_name'); $containerName = config('filesystems.disks.azure.container_name'); $sasToken = config('filesystems.disks.azure.sas_token'); $uri = "https://{$accountName}.blob.core.windows.net/{$containerName}/{$path}"; $version = '2024-05-04'; $createUri = "{$uri}?{$sasToken}"; try { $createResponse = Http::withHeaders([ 'x-ms-blob-type' => 'AppendBlob', 'x-ms-date' => gmdate('D, d M Y H:i:s T'), 'x-ms-version' => $version, 'Content-Length' => '0', ])->put($createUri, ''); if (!$createResponse->successful()) { throw new \Exception('Failed to create new blob: ' . $createResponse->body()); } } catch (\Illuminate\Http\Client\RequestException $e) { if ($e->response->status() !== 409) { throw new \Exception('Failed to create new blob: ' . $e->response->body()); } } $appendUri = "{$uri}?comp=appendblock&{$sasToken}"; $response = Http::withHeaders([ 'Content-Type' => 'application/octet-stream', 'x-ms-date' => gmdate('D, d M Y H:i:s T'), 'x-ms-version' => $version, ])->put($appendUri, $text); if ($response->successful()) { return true; } else { throw new \Exception('Failed to append content: ' . $response->body()); } }
内容的提问来源于stack exchange,提问作者ssa
相关产品推荐
相关产品推荐

