簡體   English   中英

如何從 Spring Controller 返回瀏覽器中的 CSV 數據

[英]How to Return CSV Data in Browser From Spring Controller

假設我有一個字符串中的 CSV 數據,並希望從 Spring 控制器返回它。 想象一下數據是這樣的

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

無論我嘗試過什么,換行符都會在響應內容中以字面意義的 '\\n' 形式出現,如果我像在“\\n”中那樣對它們進行雙重轉義,則響應也只包含雙反斜杠。 一般來說,如何在不修改換行符的情況下返回帶有換行符的純文本數據? 我知道如何返回純文本,但內容仍然帶有轉義的換行符......這就是我目前擁有的(使用 Spring 3.0.5,而不是選擇)

@RequestMapping(value = "/api/foo.csv")
public ResponseEntity<String> fooAsCSV() {

    HttpHeaders responseHeaders = new HttpHeaders();
    responseHeaders.add("Content-Type", "text/plain; charset=utf-8");

    String data = "a,b,c\n1,2,3\n3,4,5";
    return new ResponseEntity<>(data, responseHeaders, HttpStatus.OK);
}

從字面上產生字符串

"a,b,c\n1,2,3\n,3,4,5"

在瀏覽器中。 我如何使它產生正確的數據,如上圖所示,新行完好無損?

您可以使用例如直接寫入響應

@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");
}

由於返回類型為void並且HttpServletResponse被聲明為方法參數,因此當此方法返回時,假定請求已完成。

您可以使用庫supercsv

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

以下是如何使用它:

1- 定義您要編寫為 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- 做以下魔術:

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();
    }
}

您是否在控制器方法上嘗試過@ResponseBody

@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;
}

編輯:Spring 文檔在這里解釋: http : //docs.spring.io/spring/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc-ann-responsebody

這是巴特回答的更詳細示例:

@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);
    }
}

我最近有一個類似的任務。 使用ResponseEntity<byte[]>和響應頭Content-Disposition 像這樣:

@RequestMapping(value = "/api/foo.csv")
public ResponseEntity<byte[]> fooAsCSV() {

  HttpHeaders responseHeaders = new HttpHeaders();
  responseHeaders.add("Content-Type", "application/vnd.ms-excel");
  responseHeaders.add("Content-Disposition", "attachment; filename=abc.csv");

  String data = "a,b,c\n1,2,3\n3,4,5";
  return new ResponseEntity<>(data.getBytes("ISO8859-15"), responseHeaders, HttpStatus.OK);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM