Olá Guilherme, estou utilizando Spring Boot e Angular 7 num sistema aqui, e faço da seguinte forma:
No meu Component onde tenho o download terei o seguinte:
TS:
download(anexo: Anexo) {
const url = URL.createObjectURL(
this.ioService.base64ToBlob(
anexo.conteudo,
anexo.contentType,
512)
);
window.open(url);
}
HTML:
<button type="button" class="..." (click)="download(anexo)" >
Download
</button>
io-service.ts:
/**
* Convert a base64 string in a Blob according to the data and contentType.
*
* @param base64Data {String} Pure base64 string without contentType
* @param contentType {String} the content type of the file i.e (application/pdf - text/plain)
* @param sliceSize {Int} SliceSize to process the byteCharacters
* @see http://stackoverflow.com/questions/16245767/creating-a-blob-from-a-base64-string-in-javascript
* @return Blob
*/
base64ToBlob(base64Data: string, contentType: string, sliceSize: number): Blob {
contentType = contentType || '';
sliceSize = sliceSize || 512;
const byteCharacters = atob(base64Data);
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++) {
byteNumbers[i] = slice.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
const blob = new Blob(byteArrays, {type: contentType});
return blob;
}
No meu Controller (SpringBoot) eu retorno o arquivo como base64, então é simplesmente um atributo string, sem mistério. Na realidade retorno uma lista de anexos (AnexoTO):
@GetMapping("/v1/anexo/filtro/{associacaoId}")
public ResponseEntity<?> filterGet(HttpServletRequest request, @PathVariable("associacaoId") Long associacaoId) {
try {
List<AnexoTO> list = service().consultarPorAssociacao(associacaoId);
return prepareResponseList(list);
} catch (Exception e) {
logger.error(e.getMessage(), e);
return buildResponseError(messageFactory.error("ERR_005", e));
}
}
AnexoTO:
public class AnexoTO implements Serializable, Comparable<AnexoTO> {
private Long id;
private String nome;
private TipoAnexoEnum tipoAnexo;
private String conteudo;
private String contentType;
...
}
Também mantenho o contentType do arquivo, para saber como abrir no download.
No meu caso eu salvo dados do anexo (arquivo) no banco de dados, mas o conteúdo do arquivo salvo no FileSystem, mas poderia ser no banco também. Mas isso é indiferente.
No teu caso, deverás "zipar" os arquivos e fazer base64 desse Zip retornando um objeto (que o SpringBoot transformará num JSON), sendo o contentType application/zip.
Pra ler o arquivo do FileSystem como String faço o seguinte:
public String loadFromFileSystem(String conteudo) throws IOException {
String filename = conteudo;
Path path = Paths.get(anexoRootFolder + File.separator + filename);
if (Files.exists(path)) {
return new String(Files.readAllBytes(path));
}
return null;
}
Isso tudo está funcionando em produção "like a charm", só fazer as devidas adaptações:
Espero que tenha ajudado.
Att.