skip to Main Content

I’ve created a download button to get a zip file of product photos. It works fine when testing in localhost but doesnt work after deployed to server.

No zip file was created and there’re no error message in both web console and catalina log, nothing happened…

I once suspected it was due to file size issue. But spring boot seems to only have max upload size, not download.
And the photos sizes are around 50KB to 150KB each, max 5 photos per zip file, so size shouldnt be the issue

Has anyone encountered similar issue before? Any suggestion would be appreciated!

frontend code (jquery)
The reason that i didn’t simply use window.open(link) is because the zip file name token my backend path (i.e. downloadAttachment.zip), so I did below as a work around

$("#download").click(function(){
        var downloadLink = '<c:url value="/receiving/downloadAttachments.do"/>'
            +"?productId=${productId}";
        
        var linkElement = document.createElement("a");
        linkElement.href = downloadLink;
        linkElement.download = "product_image_${productId}.zip";
        
        document.body.appendChild(linkElement);
        linkElement.click();
        document.body.removeChild(linkElement);
})

backend code (java)
when I check the log, i realise the controller has not been called at all.

@RequestMapping(value="/downloadAttachments", method = RequestMethod.GET)
public void downloadAttachments( HttpServletRequest request, HttpServletResponse response,
    @RequestParam(value="productId", required=true)Long productId) throws IOException{
    log.debug("/downloadItemAttachments -- productId:"+productId);
        
    
        ZipOutputStream zos = new ZipOutputStream(response.getOutputStream());
            
        List<ProductInfo> attachmentList = productInfoService.findByProductId(productId);
        int contentLength = 0;
            int seq = 1;
        if(attachmentList!=null && !attachmentList.isEmpty()){  
        for(ProductInfo att : attachmentList){  
            String fileName = "item_"+productId+"_"+seq+".png";
                
            ZipEntry zipEntry = new ZipEntry(fileName);
            zos.putNextEntry(zipEntry);

                //convert base 64 str to image
            byte[] bytes = DatatypeConverter.parseBase64Binary(att.getBase64Str());
            ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
                
            int length;
            while ((length = bis.read(bytes)) >= 0) {
                log.debug("file size : "+length);
                contentLength += length;
                zos.write(bytes, 0, length);
            }
            
                
            IOUtils.copy(bis, zos);
            zos.closeEntry();
            bis.close();
        }
        log.debug("contentLength -- "+contentLength);
        zos.close();
        String zipFileName = "product_image_"+productId+".zip";
        response.setContentType("application/zip");
        response.setStatus(HttpServletResponse.SC_OK);
        response.setContentLength(contentLength);
        response.setHeader("Content-Disposition","attachment;filename=""+URLEncoder.encode(zipFileName,"UTF-8")+"""); 
        
         response.flushBuffer();    

2

Answers


  1. What I am suggesting is to trace back whether your download request to the server has the problem or the download javascript code has the problem.

    backend code (java) when I check the log, i realise the controller has
    not been called at all.

    First, check the network tab in your browser dev tools to visualize the outgoing download request towards the server.

    Double check the URL path is matching with the server path for the real server scenario. Also, see if is it due to some problem with your request params.

    Also check what response you are receiving for that call, and whether any error response codes like 400 BadRequest from the server side.

    You could further debug separately using Postman or Curl and send the same download request generated from the actual javascript code (by seeing the browser request) to the server. Then check whether it’s coming to your server or not.

    Also, one other corner case might be your server-side log level is not set to print debug level which might be the reason you are not seeing the incoming request logs if the request really coming to the server, where you could increase the verbose logs to print debug level logs.

    Or else also check if the firewall of the server is not allowing for your request.

    You could also check whether your download client javascript code is causing the problem by checking the browser console logs for any errors.

    Login or Signup to reply.
  2. The spring way of writing that is something like:

    @RequestMapping(value = "/downloadAttachments", method = RequestMethod.GET)
    public ResponseEntity<?> downloadAttachments(@RequestParam(value = "productId", required = true) Long productId) throws IOException {
        log.debug("/downloadItemAttachments -- productId:" + productId);
        List<ProductInfo> attachmentList = productInfoService.findByProductId(productId);
        String zipFileName = "product_image_" + productId + ".zip";
        
        Consumer<OutputStream> zipproducer = os -> {
            try (ZipOutputStream zos = new ZipOutputStream(os)) {
                for (ProductInfo att : attachmentList) {
                    String fileName = "item_" + productId + "_" + seq + ".png";
    
                    ZipEntry zipEntry = new ZipEntry(fileName);
                    zos.putNextEntry(zipEntry);
    
                    //convert base 64 str to image
                    byte[] bytes = DatatypeConverter.parseBase64Binary(att.getBase64Str());
                    ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
    
                    int length;
                    while ((length = bis.read(bytes)) >= 0) {
                        log.debug("file size : " + length);
                        contentLength += length;
                        zos.write(bytes, 0, length);
                    }
    
    
                    IOUtils.copy(bis, zos);
                    zos.closeEntry();
                    bis.close();
                }
            } catch (IOException ex) {
                throw new RuntimeException(ex);
            }
        };
    
    
        HttpHeaders headers = new HttpHeaders();
        headers.setContentDisposition(ContentDisposition.builder("attachment")
                .filename(zipFileName, StandardCharsets.UTF_8)
                .build());
        headers.setContentType(MediaType.valueOf("application/zip"));
        return new ResponseEntity<>(zipproducer, headers, HttpStatus.OK);
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search