How to Return CSV Data in Browser From Spring Controller

前端 未结 4 1648
有刺的猬
有刺的猬 2020-12-08 16:12

Let say I have CSV data in a string and want to return it from a Spring controller. Imagine the data looks like this

a,b,c 
1,2,3
4,5,6

No

相关标签:
4条回答
  • 2020-12-08 16:36

    You could write to the response directly using e.g.

    @RequestMapping(value = "/api/foo.csv")
    public void fooAsCSV(HttpServletResponse response) {         
        response.setContentType("text/plain; charset=utf-8");
        response.getWriter().print("a,b,c\n1,2,3\n3,4,5");
    }
    

    Since the return type is void and HttpServletResponse is declared as a method argument the request is assumed to be completed when this method returns.

    0 讨论(0)
  • 2020-12-08 16:50

    Have you tried @ResponseBody on your controller method?

    @RequestMapping(value = "/api/foo.csv")
    @ResponseBody
    public String fooAsCSV(HttpServletResponse response) {         
        response.setContentType("text/plain; charset=utf-8");
        String data = "a,b,c\n1,2,3\n3,4,5";
        return data;
    }
    

    Edit: Spring docs explain it here: http://docs.spring.io/spring/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc-ann-responsebody

    0 讨论(0)
  • 2020-12-08 17:00

    here is a more detailed example for Bart's answer:

    @GetMapping(value = "csv")
    public void exportCsv(HttpServletResponse response) {
        try {
            // prepare response encoding and Headers
            response.setContentType("text/csv");
            response.setCharacterEncoding(StandardCharsets.UTF_8.name());
            response.setHeader("Content-Disposition", "attachment; filename=a.csv"); // specify the real file name users will get when download
            try (Writer writer = new OutputStreamWriter(response.getOutputStream(), StandardCharsets.UTF_8)) {
                // writer.write('\uFEFF'); // BOM is essential in some scenary
                writer.write("key,value\n");
                List<Row> row = rowService.getAll();
                for (Column column : row) {
                    writer.write(String.format("%d,%s)\n",column.getKey(), column.getValue()));
                }
                writer.flush(); // DONNOT forget to flush writer after everything done
            } // writer will be closed automatically
        } catch (IOException e) {
            log.error("failed to export csv", e);
        }
    }
    
    0 讨论(0)
  • 2020-12-08 17:02

    You can use the library supercsv.

    <dependency>
      <groupId>net.sf.supercsv</groupId>
      <artifactId>super-csv</artifactId>
      <version>2.1.0</version>
    </dependency>
    

    Here is how to use it:

    1- define your model class that you want to write as csv:

    public class Book {
    private String title;
    private String description;
    private String author;
    private String publisher;
    private String isbn;
    private String publishedDate;
    private float price;
    
    public Book() {
    }
    
    public Book(String title, String description, String author, String publisher,
            String isbn, String publishedDate, float price) {
        this.title = title;
        this.description = description;
        this.author = author;
        this.publisher = publisher;
        this.isbn = isbn;
        this.publishedDate = publishedDate;
        this.price = price;
    }
    
    // getters and setters...
    }
    

    2- Do the following magic:

    import java.io.IOException;
    import java.util.Arrays;
    import java.util.List;
    
    import javax.servlet.http.HttpServletResponse;
    
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.supercsv.io.CsvBeanWriter;
    import org.supercsv.io.ICsvBeanWriter;
    import org.supercsv.prefs.CsvPreference;
    
    /**
     * This Spring controller class implements a CSV file download functionality.
     *
     */
    @Controller
    public class CSVFileDownloadController {
        @RequestMapping(value = "/downloadCSV")
        public void downloadCSV(HttpServletResponse response) throws IOException {
    
            String csvFileName = "books.csv";
    
            response.setContentType("text/csv");
    
            // creates mock data
            String headerKey = "Content-Disposition";
            String headerValue = String.format("attachment; filename=\"%s\"",
                csvFileName);
            response.setHeader(headerKey, headerValue);
    
            Book book1 = new Book("Effective Java", "Java Best Practices",
                "Joshua Bloch", "Addision-Wesley", "0321356683", "05/08/2008",
                38);
    
            Book book2 = new Book("Head First Java", "Java for Beginners",
                "Kathy Sierra & Bert Bates", "O'Reilly Media", "0321356683",
                "02/09/2005", 30);
    
            Book book3 = new Book("Thinking in Java", "Java Core In-depth",
                "Bruce Eckel", "Prentice Hall", "0131872486", "02/26/2006", 45);
    
            Book book4 = new Book("Java Generics and Collections",
                "Comprehensive guide to generics and collections",
                "Naftalin & Philip Wadler", "O'Reilly Media", "0596527756",
                "10/24/2006", 27);
    
            List<Book> listBooks = Arrays.asList(book1, book2, book3, book4);
    
            // uses the Super CSV API to generate CSV data from the model data
            ICsvBeanWriter csvWriter = new CsvBeanWriter(response.getWriter(),
                CsvPreference.STANDARD_PREFERENCE);
    
            String[] header = { "Title", "Description", "Author", "Publisher",
                "isbn", "PublishedDate", "Price" };
    
            csvWriter.writeHeader(header);
    
            for (Book aBook : listBooks) {
                csvWriter.write(aBook, header);
            }
    
            csvWriter.close();
        }
    }
    
    0 讨论(0)
提交回复
热议问题