Configuring Spring MVC controller to send file to client

后端 未结 2 544
暗喜
暗喜 2020-12-04 22:05

I think my scenario is pretty common. I have a database and I want my Spring MVC app to accept a request in the controller, invoke the DB service to get data an

2条回答
  •  眼角桃花
    2020-12-04 23:01

    It seems to be because your Content-type is set incorrectly, it should be response.setContentType("text/csv;charset=utf-8") instead of response.setContentType("data:text/csv;charset=utf-8").

    Additionally, if you are using Spring 3, you should probably use a @ResponseBody HttpMessageConverter for code reuse. For example:

    • In the controller:

      @RequestMapping(value = "/getFullData2.html", method = RequestMethod.GET, consumes = "text/csv")
      @ResponseBody // indicate to use a compatible HttpMessageConverter
      public CsvResponse getFullData(HttpSession session) throws IOException {
            List allRecords = compReqServ.getFullDataSet((String) session.getAttribute("currentProject"));
            return new CsvResponse(allRecords, "yourData.csv");
      }
      
    • plus a simple HttpMessageConverter:

      public class CsvMessageConverter extends AbstractHttpMessageConverter {
         public static final MediaType MEDIA_TYPE = new MediaType("text", "csv", Charset.forName("utf-8"));
         public CsvMessageConverter() {
             super(MEDIA_TYPE);
         }
      
         protected boolean supports(Class clazz) {
             return CsvResponse.class.equals(clazz);
         }
      
         protected void writeInternal(CsvResponse response, HttpOutputMessage output) throws IOException, HttpMessageNotWritableException {
             output.getHeaders().setContentType(MEDIA_TYPE);
             output.getHeaders().set("Content-Disposition", "attachment; filename=\"" + response.getFilename() + "\"");
             OutputStream out = output.getBody();
             CsvWriter writer = new CsvWriter(new OutputStreamWriter(out), '\u0009');
             List allRecords = response.getRecords();
             for (int i = 1; i < allRecords.size(); i++) {
                  CompositeRequirement aReq = allRecords.get(i);
                  writer.write(aReq.toString());
             }
             writer.close();
         }
      }
      
    • and a simple object to bind everything together:

      public class CsvResponse {    
         private final String filename;
         private final List records;
      
         public CsvResponse(List records, String filename) {
             this.records = records;
             this.filename = filename;
         }
         public String getFilename() {
             return filename;
         }
         public List getRecords() {
             return records;
         }
      }
      

提交回复
热议问题