Spring Boot Controller export an Excel

后端 未结 5 1294
悲&欢浪女
悲&欢浪女 2021-02-06 12:22

I have a java/spring boot application where I want to build an API endpoint that creates and returns a downloadable excel file. Here is my controller endpoint:

@         


        
5条回答
  •  悲哀的现实
    2021-02-06 12:36

    Basically , there are few points that you first need to understand & then decide what you want to do ,

    1.Is excel creation on disk needed or can you stream it from memory?

    If its a download pop up, user might keep it open for long time & memory be occupied during that period ( disadvantage of in memory approach ) .

    Secondly, if generated file has to be new for each request ( i.e. data to be exported is different ) then there is no point in keeping it at disk ( disadvantage of in disk approach ) .

    Thirdly, it will be hard for an API code to do disk clean up because you never know in advance as when user will finish up his down load ( disadvantage of in disk approach ) .

    Answer by Fizik26 is this In - Memory approach where you don't create a file on disk. . Only thing from that answer is that you need to keep track of length of array out.toByteArray() & that can easily be done via a wrapper class.

    2.While downloading a file , your code needs to stream a file chunk by chunk - thats what Java streams are for. Code like below does that.

    return ResponseEntity.ok().contentLength(inputStreamWrapper.getByteCount())
                .contentType(MediaType.parseMediaType("application/vnd.ms-excel"))
                .cacheControl(CacheControl.noCache())
                .header("Content-Disposition", "attachment; filename=" + "SYSTEM_GENERATED_FILE_NM")
                .body(new InputStreamResource(inputStreamWrapper.getByteArrayInputStream()));
    

    and inputStreamWrapper is like ,

    public class ByteArrayInputStreamWrapper {
        private ByteArrayInputStream byteArrayInputStream;
        private int byteCount;
    
    
        public ByteArrayInputStream getByteArrayInputStream() {
        return byteArrayInputStream;
        }
    
    
        public void setByteArrayInputStream(ByteArrayInputStream byteArrayInputStream) {
        this.byteArrayInputStream = byteArrayInputStream;
        }
    
    
        public int getByteCount() {
        return byteCount;
        }
    
    
        public void setByteCount(int byteCount) {
        this.byteCount = byteCount;
        }
    
    }
    

    Regarding file name, if file name is not an input to end point - that means ..its system generated ( a combination of constant string plus a variable part per user ). I am not sure why you need to get that from resource.

    You won't need this wrapper if use - org.springframework.core.io.ByteArrayResource

提交回复
热议问题