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

Download de qualquer arquivo

component

download(idArquivo: number): void {
    this.arquivosService.downloadArquivoOrcamento(idArquivo).subscribe(
      data => {
        const blob = new Blob([data.arquivo], { type: 'text/json; charset=utf-8' });
        const url= window.URL.createObjectURL(blob);
        window.open(url);
      },
      err => {
        console.error(err);
      }
    )
  }

Service import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { SERVER_API_URL } from 'app/app.constants'; import { Observable } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class ArquivosService { constructor( private http: HttpClient ) {} downloadArquivoOrcamento(id: number, tipo: string): Observable { return this.http.get(SERVER_API_URL + '/api/orcamento-anexo/' + id, { responseType: 'blob', headers: new HttpHeaders().append('Content-Type', tipo) }); } } Retorno do backend Não retorna o arquivo conforme imagem anterior Dowload com erro

O que pode ser ?

9 respostas

Fala ai Guilherme, tudo bem? Provavelmente ele não está encontrando esse arquivo, isso porque o blob pode somente ser usado pela mesma sessão do navegador e quando você faz window.open trata-se de uma nova sessão.

Espero ter ajudado.

Ajudou um pouco. A questão é que tentei um monte de solução e não consigo fazer o download do arquivo

Sendo que o contetType, o nome e o arquivo binário já vem do servidor.

Isso entendeu ?

Fala Guilherme, sim eu entendi todo o código.

Nesse caso, o problema seria o window.open como comentei anteriormente, isso porque o link temporário é restrito por sessões do navegador.

O que você pode fazer é em vez de abrir uma nova aba, você faz o download em si do arquivo:

Exemplo: http://jsfiddle.net/koldev/cW7W5/

Uma das maneiras de fazer isso é com o Blob e a.

Espero ter ajudado.

Obrigado vou testar e coloco o resultado aqui

Ele faz o downloading, com o nome que infomei

No caso é um png e quando abro, ele mostra um arquivo com escrito assim: "Não há suporte para este formato de arquivo".

O código fico assim:

download(idArquivo: number, tipo: string): void {
    this.arquivosService.downloadArquivoOrcamento(idArquivo, tipo).subscribe(
      (data: any) => {
        const a = document.createElement('a');
        document.body.appendChild(a);
          const json = JSON.stringify(data.arquivo),
              blob = new Blob([json], {type: tipo}),
              url = window.URL.createObjectURL(blob);
          a.href = url;
          a.download = 'fileName';
          a.click();
          window.URL.revokeObjectURL(url);
      },
      err => {
        console.error(err);
      }
    )
  }

Fala Guilherme, precisa ver como foi criado o arquivo, ou seja, o conteúdo dele.

Precisa ver como está a variável tipo, se criou na extensão correto e o valor do Blob, você marcou como JSON, precisa ver o que tem nessa variável JSON.

Isso porque cada tipo de arquivo espera um tipo de conteúdo, se ambos não derem match eles vão dar problemas.

Espero ter ajudado.

Meu incluir está assim:

service

incluir(orcamento: IOrcamentoIncluirModel, files: File[]): Observable<EntityResponseType> {
    const orcamentoIncluir = 'dto';
    const filesServer = 'files';
    const formData: FormData = new FormData();
    if(files !== undefined) {
      for (let i = 0; i < files.length; i++) {
        const blob: Blob = new Blob([JSON.stringify(orcamento)], {type: 'application/json'});
        formData.append(orcamentoIncluir, blob);
        formData.append(filesServer, files[i]);
      }
    }
    return this.http
      .post<IOrcamentoIncluirModel>(this.api + 'incluir', formData, { observe: 'response' })
      .pipe(map((res: EntityResponseType) => this.convertDataParaServidor(res)));
}

Java

endpont

@PostMapping(value = "incluir")
@PreAuthorize("hasAuthority('" + ADMINISTRADOR + "') ")
public ResponseEntity<?> incluir(@Valid @RequestPart OrcamentoIncluirDTO dto,
    @RequestPart Collection<MultipartFile> files) {
    try {
        log.info("Metodo que inclui um orcamento");
        OrcamentoDTO orcamento = service.incluir(dto, files);
        log.info("Com o id: " + orcamento.getId());
        orcamento.setMensagem(mensagemSalvar(false));
        return new ResponseEntity<>(orcamento, OK);
    } catch (Exception e) {
        log.error(e.getMessage(), e);
        throw new BadRequestAlertException(e.getMessage(), ORCAMENTO, null);
    }
}

Serviço

private Collection<OrcamentoAnexo> ajustesAnexos(Collection<MultipartFile> anexos, Orcamento orcamento) {
        log.info("Metodo que faz ajustes em anexos para o orçamento");
        Collection<OrcamentoAnexo> anexosBanco = new ArrayList<>();
        if (anexos != null && !anexos.isEmpty()) {
            anexos.forEach(anexo -> {
                OrcamentoAnexo anexoBanco;
                try {
                    anexoBanco = OrcamentoAnexo.builder().tamanho(anexo.getSize()).arquivo(anexo.getBytes())
                            .nome(anexo.getOriginalFilename()).orcamento(orcamento).contentType(anexo.getContentType())
                            .build();
                    anexosBanco.add(anexoBanco);
                    aplicacaoAuditoria(anexoBanco);
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
            });
            log.info("Total de anexos: " + anexos.size());
        }
        return anexosBanco;
    }

No Java a não ser o anexo.getBytes(), o restante está chegando correto.

solução!

Consegui desta forma

/* eslint-disable @typescript-eslint/tslint/config */
export default class DownloadUtils {

    static baixarDocumentoBase64(conteudo:any, nomeArquivo:any, mymeType:any) {
      const blob = DownloadUtils.b64toBlob(conteudo, mymeType);
      const blobUrl = URL.createObjectURL(blob);

      const downloadLink = document.createElement('a');
      downloadLink.href = blobUrl;
      downloadLink.download = nomeArquivo;
      downloadLink.click();
      downloadLink.remove();
    }

    static b64toBlob(b64Data:any, contentType:any) {
      const sliceSize = 512;
      const byteCharacters = atob(b64Data);
      const byteArrays = [];

      for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
        const slice = byteCharacters.slice(offset, offset + sliceSize);

        const byteNumbers = new Array(slice.length);
        for (let i = 0; i < slice.length; i += 1) {
          byteNumbers[i] = slice.charCodeAt(i);
        }

        const byteArray = new Uint8Array(byteNumbers);
        byteArrays.push(byteArray);
      }

      return new Blob(byteArrays, { type: contentType });
    }
  }

Fala Guilherme, fico feliz que tenha resolvido seu problema, realmente para seu caso a criação do Blob precisava ser feito de maneira diferente.

As vezes é mais complicado por não ter contexto do projeto e quais são os retornos e tals, mas, com calma a gente vai resolvendo.

Sempre que precisar não deixe de criar suas dúvidas.

Abraços e bons estudos.