Error A 'contents' key is required al enviar archivos desde una api con Http Client

Publicado por Luis Aguilar
hace 10 meses

Estoy tratando de enviar un archivo de video desde mi app en laravel mediante POST usando hacia una API,y me genera un error A 'contents' key is required e intentado todas las soluciones posibles y no encuentro la solucion.

Este es la funcion de mi controlador que recibe los datos de mi formulario POST.

public function store(Request $request)
{
    $validated = $request->validate([
        'nameVideo' => 'required|max:255',
        'videoFile' => 'required|file|mimes:mp4,mov,avi|max:3072000',
        'datePublication' => 'required|date',
        'producer' => 'required|string|in:' . implode(',', $this->producers),
        'selectArtist' => ['required', 'array', function ($attribute, $value, $fail) {
            foreach ($value as $artist) {
                if (!in_array($artist, $this->artists)) {
                    $fail("El valor $artist no es válido para el campo $attribute.");
                }
            }
        }],
        'selectCategories' => ['required', 'array', function ($attribute, $value, $fail) {
            foreach ($value as $category) {
                if (!in_array($category, $this->categories)) {
                    $fail("El valor $category no es válido para el campo $attribute.");
                }
            }
        }],
        'newCategories' => 'nullable|string',
        'descriptionVideo' => 'nullable',
    ]);

//Las validaciones se hacen correctamente

    $video = $request->file('videoFile');

    $data = [
        'nombreVideo' => $validated['nameVideo'],
        'fechaPublicacion' => $validated['datePublication'],
        'productora' => $validated['producer'],
        'listadoArtistas' => $validated['selectArtist'], // Array de artistas seleccionados
        'listadoCategorias' => $validated['selectCategories'], // Array de categorías seleccionadas
        'descripcion' => $validated['descriptionVideo'],
    ];

    // Enviar la solicitud HTTP con los datos del formulario y el video
    $response = Http::timeout(900)->asMultipart()->withHeaders([
            'Authorization' => 'Bearer ' . Session::get('api_token'),
            'Accept' => 'application/json',
        ])
        ->attach('video', file_get_contents($video->getRealPath()), $video->getClientOriginalName())
        ->post($this->endpoint_url, $data);

    return $this->handlerResponse($response, 'Error al enviar el video');
}

La api tiene que recibir un multipart/fom-data del tipo

 String nombreVideo,
    MultipartFile video,
    Date fechaPublicacion,
    String productora,
    List<String> listadoArtistas,
    List<String> listadoCategorias,
    String descripcion

y recibo el error A 'contents' key is required

Laravel 11 HttpClient post multipart attach
Respuesta de Cristian Olaz
hace 10 meses

Hola Luis,

Por empezar, imagino que ya lo hiciste pero tendrías que asegurarte que file_get_contents te está devolviendo correctamente el contenido del archivo:

dd(file_get_contents($video->getRealPath());

En segundo lugar, aparentemente en algunas versiones si enviás un archivo adjunto entonces no podés enviar los datos en la manera que lo estás haciendo. Y en su lugar tendrías que definirlos de esta manera:

$data = [
    [
        'name' => 'nombreVideo'
        'contents' => $validated['nameVideo'],
    ],
    [
        'name' => 'fechaPublicacion'
        'contents' => $validated['datePublication'],
    ],
    [
        'name' => 'productora'
        'contents' => $validated['producer'],
    ],
    [
        'name' => 'listadoArtistas'
        'contents' => $validated['selectArtist'], // Array de artistas seleccionados
    ],
    [
        'name' => 'listadoCategorias'
        'contents' => $validated['selectCategories'], // Array de categorías seleccionadas
    ],
    [
        'name' => 'descripcion'
        'contents' => $validated['descriptionVideo'],
    ],
    [
        'name' => 'video',
        'contents' => file_get_contents($video->getRealPath()),
        'filename' => $video->getClientOriginalName()
    ]
];

Y luego enviarlo como lo estabas haciendo pero sin el attach:

    $response = Http::timeout(900)->asMultipart()->withHeaders([
            'Authorization' => 'Bearer ' . Session::get('api_token'),
            'Accept' => 'application/json',
        ])
        ->post($this->endpoint_url, $data);

Espero que te sirva. Saludos,