Java - 如何通过HTTP请求而不是文件读取xls格式数据

标签 java spring-mvc apache-poi inputstream outputstream

目前,我需要为另一个发送xls格式响应的java应用程序提供一个API,而当我在本地测试时使用MockMVC从我的API获取响应并使用HSSFWorkBook来解析它,虽然它失败了,但任何人都可以帮助我展示如何用 Java 实现这个 API? 非常感谢!!!

框架:SpringMVC

我的代码:

    @RequestMapping(value = "/report", method = RequestMethod.GET)
    public ResponseEntity getReport() {
        LOGGER.info("begin to get report");
//        Workbook dailyReport = reportService.getDailyReport();
        Workbook dailyReport = new HSSFWorkbook();
        OutputStream outByteStream = new ByteArrayOutputStream();
        try {
            dailyReport.write(outByteStream);
            LOGGER.info("end to get report");
        } catch (IOException e) {
            LOGGER.error("IOException when write excel to stream, e: {}", e);
        }
        MultiValueMap<String, String> headers = new HttpHeaders();
        List<String> list = new ArrayList<>();
        list.add("application/vnd.ms-excel");
        headers.put(HttpHeaders.CONTENT_TYPE, list);
        return new ResponseEntity(outByteStream, headers, HttpStatus.OK);
    }

测试方法:

@Test
public void testGetMigrationDailyReport() {
    String url = "/report";
    try {
        MvcResult mvcResult = this.mockMvc.perform(MockMvcRequestBuilders.get(url)).andExpect(status().isOk()).andReturn();
        String response = mvcResult.getResponse().getContentAsString();
        byte[] bytes = response.getBytes();
        InputStream inputStream = new ByteArrayInputStream(bytes);

        Workbook workbook = new HSSFWorkbook(inputStream);
        Sheet sheet = workbook.getSheetAt(0);

    } catch (Exception e) {
        e.printStackTrace();
    }
}

完整的堆栈跟踪:

    org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalArgumentException: No converter found for return value of type: class java.io.ByteArrayOutputStream
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:979)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:858)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843)
    at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:65)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
    at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:167)
    at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134)
    at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:155)
    at com.cisco.csit.wbxmig.web.IntegrationControllerTest.testGetMigrationDailyReport(IntegrationControllerTest.java:59)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:254)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:193)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.IllegalArgumentException: No converter found for return value of type: class java.io.ByteArrayOutputStream
    at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:179)
    at org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:183)
    at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:81)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:126)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:832)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:743)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:961)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:895)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967)
    ... 38 more

最佳答案

我尝试过以下方法:

效果很好。不同之处在于我正在执行ByteArrayOutputStream.getBytes()

@GetMapping("/down")
public ResponseEntity<byte[]> down() throws IOException {
    ByteArrayOutputStream outByteStream = new ByteArrayOutputStream();
        Workbook wb = new HSSFWorkbook();
        for(int sNo=1;sNo<=5;sNo++) {
            Sheet sheet = wb.createSheet("s"+sNo);
            for(int i=1;i<6;i++) {
                Row row = sheet.createRow(i);
                for(int j=1;j<=5;j++) {
                    Cell cell = row.createCell(j);
                    cell.setCellValue("test "+j);
                }

            }
        }
        wb.write(outByteStream);
        wb.close();

       MultiValueMap<String, String> headers = new HttpHeaders();
       List<String> list = new ArrayList<>();
       list.add("application/vnd.ms-excel");
       headers.put(HttpHeaders.CONTENT_TYPE, list);
    return new ResponseEntity<byte[]>(outByteStream.toByteArray(),headers, HttpStatus.OK);
}

添加测试

诀窍是根据响应创建文件,然后再次读取它 根据响应创建文件

 FileOutputStream fos = new FileOutputStream("/Users/me/Desktop/output.xlsx");
 fos.write(bytes);
 fos.close();

读取文件

    FileInputStream fis = new FileInputStream("/Users/me/Desktop/output.xlsx");
    Workbook wb = WorkbookFactory.create(fis);

整个测试类

import java.io.ByteArrayOutputStream;

import java.io.FileInputStream;
import java.io.FileOutputStream;



import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers;
import org.springframework.security.web.FilterChainProxy;
import org.springframework.test.context.ContextConfiguration;

import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;

import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import com.techdisqus.App;
import com.techdisqus.config.SpringSecurityConfig;
import com.techdisqus.controller.DefaultController;

@RunWith(SpringRunner.class)
/*@SpringBootTest
@ContextConfiguration*/
@WebMvcTest(DefaultController.class)
@ContextConfiguration(classes= {App.class,SpringSecurityConfig.class
        })
@WebAppConfiguration
public class MvcTest {


      @Autowired
        private  MockMvc mockMvc;

      @Autowired
        private FilterChainProxy springSecurityFilterChain;

      @Autowired
        private WebApplicationContext wac;

      @Before
        public void setup() {
            this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac)
                .addFilters(this.springSecurityFilterChain).apply(SecurityMockMvcConfigurers.springSecurity()).build();
        }


    @Test
    public void testDown() {
        String url = "/down";
        try {

            MvcResult mvcResult = this.mockMvc.perform(MockMvcRequestBuilders.get(url)).andExpect(MockMvcResultMatchers.status().isOk()).andReturn();
            byte[] bytes = mvcResult.getResponse().getContentAsByteArray();
            FileOutputStream fos = new FileOutputStream("/Users/me/Desktop/output.xlsx");
            fos.write(bytes);
            fos.close();

            FileInputStream fis = new FileInputStream("/Users/me/Desktop/output.xlsx");
            Workbook wb = WorkbookFactory.create(fis);
            int count = wb.getNumberOfSheets();  
            System.out.println("count "+count);
            for(int i=0;i<count;i++) {
              System.out.println(wb.getSheetAt(i).getSheetName());
              //perform asserts here if needed
            }
            System.out.println("done!");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

关于Java - 如何通过HTTP请求而不是文件读取xls格式数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53406954/

相关文章:

java - Spring-data-elasticsearch “nested query throws [nested] failed to find nested object under path”异常

java - 何时使用 Hibernate 缓存(二级)?

java - 如何在 IntetlliJ 中使用 Gradle 设置 Amazon Polly SDK

java - 我在哪里定义 `springSecurityFilterChain` bean?

java - Spring Framework 5 中的问题接线 JPA 存储库

java - 将 xls 文件中的数据插入 SQLite android 时出错

java - POI 设置前景色在 if 语句中不起作用

java - 使用 GWT 为简单网页配置 CSS

java - 当页面不存在时,未在未经授权的 URL 上找到页面 404

java - Apache POI SXSSF 和 XSSF