Home > database >  Return a zip (or any file) from the server on the client browser (REST)
Return a zip (or any file) from the server on the client browser (REST)

Time:10-01

So I am using Java for my Server and Angular for the Client. I am currently working on a feature where you can select multiple files from a table and when you press on download, it generates a zip file and downloads it to your browser. As of right now, the server now creates the zip file and I can access it in the server files. All that is left to do is to make it download on the client's browser. (the zip file is deleted after the client downloads it)

After doing some research, I found out that you can use a fileOutputStream to do this. I also saw some tools like retrofit... I am using REST and this is what my code looks like. How would I achieve my goal as simply as possible?

Angular

  httpGetDownloadZip(target: string[]): Observable<ServerAnswer> {
    const params = new HttpParams().set('target', String(target)).set('numberOfFiles', String(target.length));
    const headers = new HttpHeaders().set('token', this.tokenService.getStorageToken());
    const options = {
      headers,
      params,
    };
    return this.http
      .get<ServerAnswer>(this.BASE_URL   '/files/downloadZip', options)
      .pipe(catchError(this.handleError<ServerAnswer>('httpGetZip')));
  }

Java zipping method

    public void getDownloadZip(String[] files, String folderName) throws IOException {
        [...] // The method is huge but basically I generate a folder called "Download/" in the server

        // Zipping the "Download/" folder
        ZipUtil.pack(new File("Download"), new File("selected-files.zip"));

        // what do I return ???
        return;
    }

Java context

            server.createContext("/files/downloadZip", new HttpHandler() {

                @Override
                public void handle(HttpExchange exchange) throws IOException {
                    if (!handleTokenPreflight(exchange)) { return; }
                    System.out.println(exchange.getRequestURI());
                    Map<String, String> queryParam = parseQueryParam(exchange.getRequestURI().getQuery());

                    String authToken = exchange.getRequestHeaders().getFirst("token");
                    String target = queryParam.get("target")   ",";
                    String[] files = new String[Integer.parseInt(queryParam.get("numberOfFiles"))];

[...] // I process the data in this entire method and send it to the previous method that creates a zip

                    Controller.getDownloadZip(files, folderName);

                    // what do I return to download the file on the client's browser ????
                    return;
                }
            });

CodePudding user response:

Tou can still use HttpServletRequest on the server...
Then get its OutputStream and write to it.

 @RequestMapping(method = RequestMethod.POST , params="action=downloadDocument")  
  public String downloadDocument(@RequestParam(value="documentId", required=true) String documentId,
                                HttpServletRequest request,
                                HttpServletResponse response ) 
  {     
    try {
        String docName = null;
        String documentSavePath = getDocumentSavePath();                    

    
        PDocument doc = mainService.getDocumentById(iDocumentId);
        
        if(doc==null){
            throw new RuntimeException("document with id: "   documentId   " not found!");
        }
        
        docName = doc.getName();
        String path = documentSavePath   ContextUtils.fileSeperator()    docName;   
        response.setHeader("Content-Disposition", "inline;filename=\""   docName   "\"");
        OutputStream out = response.getOutputStream();
        response.setContentType("application/word");
            
        FileInputStream stream = new FileInputStream(path);
        IOUtils.copy(stream, out);
        out.flush();
        out.close();
        
        } catch(FileNotFoundException fnfe){
                logger.error("Error downloading document! - document not found!!!! "   fnfe.getMessage() , fnfe);           
        } catch (IOException e) {
                logger.error("Error downloading document!!! "   e.getMessage(),e);          
        }
        return null;
    }

CodePudding user response:

You could try using responseType as arraybuffer.

Eg:

return this.http.get(URL_API_REST   'download?filename='   filename, {
    responseType: 'arraybuffer'
  });
  • Related