Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

Solução desafio upload binário

Fala pessoal, essa foi a solução que me veio na cabeça, acredito que tem como melhorar, utilizando um arquivo em memória ao invés de um arquivo "físico" temporário, vou estudar isso com calma depois, mas assim já "funciona", espero que sirva de base para quem estava na dúvida.

public function upload(Request $request)
    {
        // pega o binário e salva em uma varíavel (string)
        $binary = $request->getContent();
        // cria um arquivo temporário
        $tempFileName = tempnam('/tmp', 'tmp');
        // copia a string com o binário (o arquivo em si) para o arquivo temporário
        file_put_contents($tempFileName, $binary);
        // Mantem o parâmetro passado na rota consistente com o nome do diretório
        $pathDirectory = str_replace('-', '_', $request->query('path'));
        // Aqui é utilizado o putFile() que automaticamente gera um nome de arquivo único, porém ele precisa
        // de um arquivo "pronto"
        $storedFile = Storage::disk('public')->putFile($pathDirectory, new File($tempFileName));
        // Remove o arquivo temporário que não será mais utilizado
        unlink($tempFileName);
        // Retorna o path do arquivo para ser usado na rota de criar série
        return $storedFile;
    }
2 respostas
solução!

Refiz a função para usar um nome único e não precisar gerar um arquivo para isso. reduzindo overhead (assim acredito eu haha):

public function upload(Request $request)
    {
        $binaryData = $request->getContent();

        $uniqueFileName = md5(uniqid(microtime(), true));
        $fileExtension = substr(strrchr(getimagesizefromstring($binaryData)['mime'], '/'), 1);
        $fileName = "$uniqueFileName.$fileExtension";

        Storage::disk('public')->put("series_cover/$fileName", $binaryData);

        return "series_cover/$fileName";
    }

Acredito que um md5 de um uniqid em cima de um microtime torne quase impossível repetir o nome de um arquivo, talvez seja meio overkill (ou não...).

O método put() aceita uma string então não precisa instanciar um File a partir de um arquivo real.

Salve Guilherme! Excelente exemplo, vou deixar o meu exemplo aqui também como opção, eu criei um controlador só para upload com uma ação POST que recebe onde o arquivo deve ser salvo (path) e o arquivo propriamente dito (file), como resposta temos o "local/arquivo-salvo" pronto para ser usado em uma atualização da série:

    public function upload(Request $request)
    {
        $path = $request->query('path');

        $coverPath = $request->hasFile('file')
            ? $request->file('file')->store($path, 'public')
            : '';

        $statusCode = $coverPath !== '' ? 200 : 500;
        return response()->json($coverPath, $statusCode);
    }

Como ficou no postman:

curl --location --request POST 'http://localhost:8000/api/upload?path=series_cover' \
--header 'Cookie: XSRF-TOKEN=token_maroto' \
--form 'file=@"/C:/Imagens/minha-imagem-joia.png"'