Currently I am trying to implement a download file from a tree. A tree has children and attachments. The user can select multiple children tree or multiple attachments. Backend server should collect the data from a database and build a zip file based on a tree. Please let me know if I am implementing it correctly.
download file service.ts
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { environment } from 'src/environments/environment';
@Injectable({
providedIn: 'root'
})
export class DownloadService {
downloadList: any[] = [];
downloadAttachmentList: any[] = [];
isDownloadInQueue = false;
constructor(
private http: HttpClient
) { }
clear() {
this.downloadList.splice(0, this.downloadList.length);
this.downloadAttachmentList.splice(0, this.downloadAttachmentList.length);
this.isDownloadInQueue = false;
}
addDownloadItemToList(node: any) {
this.isDownloadInQueue = true;
this.downloadList.push(node);
}
removeDownloadItemToList(node: any) {
let nodeIndex = this.downloadList.indexOf(node);
if(nodeIndex >= 0) {
// remove it
this.downloadList.splice(nodeIndex, 1);
if(this.downloadList.length == 0 && this.downloadAttachmentList.length == 0)
this.isDownloadInQueue = false;
}
}
addDownloadAttachmentItemToList(node: any) {
this.isDownloadInQueue = true;
this.downloadAttachmentList.push(node);
}
removeDownloadAttachmentItemToList(node: any) {
let nodeIndex = this.downloadAttachmentList.indexOf(node);
if(nodeIndex >= 0) {
// remove it
this.downloadAttachmentList.splice(nodeIndex, 1);
if(this.downloadAttachmentList.length == 0 && this.downloadAttachmentList.length == 0)
this.isDownloadInQueue = false;
}
}
downloadFilesAsZip(nodeName: string | undefined) {
return this.http.post(`${environment.server}/download`, {
children: this.downloadList,
attachments: this.downloadAttachmentList,
nodeName: nodeName
}, {
responseType: 'arraybuffer'
});
}
}
folder explorer.ts
toggleDownloadSelected(selected_leaf: any, event: any) {
if(event.target.checked)
this.downloadService.addDownloadItemToList(selected_leaf);
else
this.downloadService.removeDownloadItemToList(selected_leaf);
}
toggleDownloadAttachmentSelected(selected_leaf: any, event: any) {
if(event.target.checked)
this.downloadService.addDownloadAttachmentItemToList(selected_leaf);
else
this.downloadService.removeDownloadAttachmentItemToList(selected_leaf);
}
html template.htlm
<span>
<input type="checkbox" (change)="toggleDownloadSelected(leaf, $event)"/>
</span>
package com.example.treetable;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@RestController
@RequestMapping("download")
@CrossOrigin("http://localhost:4200")
public class DownloadController {
@Autowired
private AttachmentDataRepository attachmentDataRepository;
@PostMapping
@RequestMapping(produces = "application/zip")
public void downloadResourceAsZip(
@RequestBody FileTreeDto fileTree,
HttpServletResponse response
) throws IOException {
List<AttachmentData> dataList = attachmentDataRepository.findAll();
ZipOutputStream zos = new ZipOutputStream(response.getOutputStream());
createListOfZipEntry(fileTree, fileTree.getNodeName() , zos);
zos.closeEntry();
zos.close();
}
private List<ZipEntry> createListOfZipEntry(FileTreeDto fileTreeDto, String rootPath, ZipOutputStream zos) throws IOException {
List<ZipEntry> zipEntries = new ArrayList<>();
String newRootPath = rootPath "/" fileTreeDto.getNodeName();
// check if attachement arrays exist
if(fileTreeDto.getAttachments() != null) {
for(AttachmentDataDto dataDto: fileTreeDto.getAttachments()) {
System.out.println("Getting by id " dataDto.getAttachment_id());
Optional<AttachmentData> optionalAttachmentData = attachmentDataRepository.findById(dataDto.getAttachment_id());
if(optionalAttachmentData.isPresent()) {
AttachmentData data = optionalAttachmentData.get();
String path = newRootPath "/" dataDto.getName();
System.out.println("Path " path);
ZipEntry zipEntry = new ZipEntry(path);
zipEntry.setSize(data.getFile().length);
zos.putNextEntry(zipEntry);
zos.write(data.getFile());
zipEntries.add(zipEntry);
}
}
}
if(fileTreeDto.getChildren() == null || fileTreeDto.getChildren().size() <= 0)
return zipEntries;
for (FileTreeDto ftD : fileTreeDto.getChildren()) {
zipEntries.addAll(createListOfZipEntry(ftD, newRootPath , zos));
}
return zipEntries;
}
}
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class FileTreeDto {
private String nodeName;
private List<FileTreeDto> children;
private List<AttachmentDataDto> attachments;
}
CodePudding user response:
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class AttachmentRequestDto {
private Long id;
private String name;
private Long attachment_id;
}
CodePudding user response:
downloadFile() {
if(!this.downloadService.isDownloadInQueue) return;
this.downloadService.downloadFilesAsZip(this.selected_leaf?.nodeName)
.subscribe(
res => {
const blob = new Blob([res], {
type: 'application/zip'
});
const url = window.URL.createObjectURL(blob);
window.open(url);
this.downloadService.clear();
}
);
}