AngularJS faz upload de vários arquivos com a API FormData

Eu preciso fazer upload de arquivos de imagem e vídeo para o servidor em um aplicativo Angular usando o Laravel 5.1 como back-end. Todas as requisições Ajax precisam ir primeiro para o controlador Laravel, e nós temos o código lá para como o arquivo é manipulado quando chegar lá. Anteriormente, fizemos formulários HTML normais para enviar uploads de arquivos para o controlador, mas, nesse caso, precisamos evitar a atualização de página de um formulário, portanto, estou tentando fazer isso no Ajax por meio do Angular.

Quais informações eu preciso enviar para o controlador Laravel com o Ajax que estava sendo enviado para o controlador através de um formulário HTML anteriormente?

Este é o código no controlador do Laravel que lidou com as informações do arquivo assim que chegou lá. Isso é o que eu preciso descobrir como enviar, para que eu possa reutilizar este código:

$promotion = Promotion::find($id); if (Input::hasFile('img_path')){ $path = public_path().'/images/promotion/'.$id.'/'; $file_path = $path.'promotion.png'; $delete = File::delete($file_path); $file = Input::file('img_path'); $uploadSuccess = $file->move($path, 'promotion.png'); $promotion->img_path = '/images/promotion/'.$id.'/promotion.png'; } if (Input::hasFile('video_path')){ $path = public_path().'/video/promotion/'.$id.'/'; $file_path = $path.'promotion.mp4'; $delete = File::delete($file_path); $file = Input::file('video_path'); $uploadSuccess = $file->move($path, 'promotion.mp4'); $promotion->video_path = '/video/promotion/'.$id.'/promotion.mp4'; } 

Como você pode ver acima, estamos convertendo qualquer arquivo que chegarmos a um PNG com o nome de arquivo promotion.png, então é fácil buscar, e estamos aceitando apenas o formato de vídeo .mp4. Por causa disso, não precisamos nos preocupar em verificar se o arquivo existe e está tudo bem em sobrescrevê-lo. É por isso que você pode ver no código que excluímos qualquer arquivo existente com esse nome antes de salvá-lo.

O HTML era apenas uma input com um tipo de “arquivo:

  

Estamos usando o Angular agora, então não posso mais enviar o acima através de um formulário HTML. É o que preciso para descobrir como fazer.

Somos dois desenvolvedores que estão apenas dando o nosso melhor, então tenho certeza de que há uma maneira melhor de fazer isso. No entanto, antes de refatorar tudo isso, espero usar o Angular (ou o jQuery como último recurso) para enviar ao controlador os dados de arquivo necessários para que o código acima funcione. A resposta pode ser tão simples quanto “enviar um PUT para o método no controlador acima, mas em vez de um payload JSON normal, use as informações do arquivo nesse formato e você poderá reunir essas informações com …”

Eu também gostaria de receber dicas sobre melhores maneiras de fazer isso no futuro.

Como POSTAR FormData Usando o Serviço $ http

Ao usar a API FormData para arquivos e dados POST, é importante definir o header Content-Type como undefined .

 var fd = new FormData() for (var i in $scope.files) { fd.append("fileToUpload", $scope.files[i]); } var config = {headers: {'Content-Type': undefined}}; var httpPromise = $http.post(url, fd, config); 

Por padrão, o framework AngularJS usa o tipo de conteúdo application/json . Definindo Content-Type: undefined , a estrutura AngularJS omite o header do tipo de conteúdo, permitindo que a API do XHR defina o tipo de conteúdo. Ao enviar um object FormData , a API do XHR define o tipo de conteúdo para multipart/form-data com os limites apropriados e a codificação base64 .

Para obter mais informações, consulte Referência da API da Web do MDN – Método de envio XHR


Como você obteve as informações do arquivo em $scope.files ?

Como habilitar para trabalhar com ng-model

Essa diretiva também permite que o trabalhe automaticamente com as diretivas ng-change e ng-form .

 angular.module("app",[]); angular.module("app").directive("selectFilesNg", function() { return { require: "ngModel", link: function postLink(scope,elem,attrs,ngModel) { elem.on("change", function(e) { var files = elem[0].files; ngModel.$setViewValue(files); }) } } }); 
   

AngularJS Input `type=file` Demo

NameDateSizeType
{{file.name}} {{file.lastModified | date : 'MMMdd,yyyy'}} {{file.size}} {{file.type}}