转载请注明来源-作者@loongshawn: http://blog.csdn.net/loongshawn/article/details/51996801

1、背景说明

业务中有时候会碰到利用java 处理excel文件(生成、下载、上传),通常生成一个excel文件会把它写入到机器的一个临时路径,但有时候完全没必要把它存下来,只需要在内存中把这个文件转为输入流,至于后面怎么处理都行。

2、所需依赖包

Java中创建excel文件利用到了以下两个依赖包poi-3.14.jar、poi-ooxml-3.14.jar:

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.14</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.14</version>
</dependency>   

3、excel文件处理方式

3.1、方式一:保存为本地文件

通常在创建XSSFWorkbook后,可以通过以下这种方式来存储该表格,即利用FileOutputStream把文件写入其中,这个FileOutputStream指定了文件系统存在的路径:

XSSFWorkbook wb = new XSSFWorkbook(); //创建工作薄 Sheet sheet = wb.createSheet( "Sheet0" ); //创建工作表,名称为test // 获取文件路径 filePath = "d://" +filename+ "tongji.xls" ; //文件输出 try { FileOutputStream out = new FileOutputStream(filepath); // FileOutputStream out = new FileOutputStream("d://"+filename+"tongji.xls"); wb.write(out); out.close(); result_return = true ; logger.info( "ExcelService createExcelTable Result: " + result_return); } catch (IOException e) { // TODO Auto-generated catch block // e.printStackTrace(); result_return = false ; logger.error( "ExcelService createExcelTable Error: " + e);

3.2、方式二:保存为输入流

将XSSFWorkbook对象保存为输入流时,利用到了ByteArrayOutputStream来做缓存,先将文件写入其中,然后将其转为字节数组,最后利用ByteArrayInputStream转为输入流,供后续使用。

XSSFWorkbook wb = new XSSFWorkbook(); //创建工作薄 Sheet sheet = wb.createSheet( "Sheet0" ); //创建工作表,名称为test ByteArrayInputStream in = null ; try { ByteArrayOutputStream os = new ByteArrayOutputStream(); wb.write(os); byte [] b = os.toByteArray(); in = new ByteArrayInputStream(b); os.close(); } catch (IOException e) { // TODO Auto-generated catch block // e.printStackTrace(); logger.error( "ExcelUtils getExcelFile error:{}" ,e.toString()); return null ; return in;

3.3、FileOutputStream与ByteArrayOutputStream之间的区别

要了解FileOutputStream与ByteArrayOutputStream之间的区别,需要查阅 java API

先来看看API中对FileOutputStream的描述:

FileOutputStream需要指定具体文件或者文件描述路径,才能完成数据写入,可以把它理解为一个管道,管道不能存数据。

再来看看API中对ByteArrayOutputStream的描述:

ByteArrayOutputStream定义了一个ByteArray的输出流,能够往里面写入数据,其实就是内存中的一个对象,同时实现了OutputStream。可以把它理解为一个自带管道的容器,容器能直接存数据。

4、上传OSS

接收到了excel文件的输入流后,利用OSS接口实现上传。

public static String uploadOSS(ByteArrayInputStream input,String issuenumber){
        String url = null;
        if(input != null){
            String fileName = issuenumber + "_工单详情.xlsx";
            try {
                HttpPost httpPost = new HttpPost("http://127.0.0.1/api/attachment/oss");
                httpPost.addHeader("key","12345");
                httpPost.addHeader("user","xiaomen");
                httpPost.addHeader("method","FeedbackSelect");
                httpPost.addHeader("filename",new String(fileName.getBytes("UTF-8"),"ISO-8859-1"));         
                httpPost.addHeader("type","01");
                InputStreamEntity reqEntity = new InputStreamEntity(input);         
                httpPost.setEntity(reqEntity);  
                HttpClient client = new DefaultHttpClient();
                HttpResponse response = client.execute(httpPost);
                HttpEntity responseEntity = response.getEntity();
                if(responseEntity != null){
                    InputStream inputStream = responseEntity.getContent();  
                    String data = convertStreamToString(inputStream);   
                    logger.info("FileUpload2OSS uploadOSS data:{}",data);   
                    JSONObject json = JSON.parseObject(data);
                    if(json.containsKey("statusCode")){
                        int statusCode = json.getIntValue("statusCode");
                        if(statusCode == 0){
                            JSONArray array = json.getJSONArray("responseData");
                            JSONObject j = array.getJSONObject(0);
                            url = j.getString("attachment");
                input.close();
            } catch (UnsupportedEncodingException e) {
                // TODO Auto-generated catch block
                // e.printStackTrace();
                logger.error("FileUpload2OSS uploadOSS UnsupportedEncodingException:{}",e.toString());  
                return url;
            } catch (ClientProtocolException e) {
                // TODO Auto-generated catch block
                // e.printStackTrace();
                logger.error("FileUpload2OSS uploadOSS ClientProtocolException:{}",e.toString());   
                return url;
            } catch (IOException e) {
                // TODO Auto-generated catch block
                // e.printStackTrace();
                logger.error("FileUpload2OSS uploadOSS IOException:{}",e.toString());   
                return url;
        return url;

针对具体业务可以自由选择处理方式。如果无需存储文件至系统,则考虑第二种方式。

在我自己的业务中,使用了第二种方式,无需将生成的excel存在服务器即可完成上传线上OSS。

结果样例:http://url.na

由于需求。。 使用了ByteArrayOutputStream和ByteArrayInputStream类. 将XSSFWorkbook 写入ByteArrayOutputStream.然后用ByteArrayOutputStream来换为字节流.然后再将字节流换为ByteArrayInputStream …至此,我们就在内存中将excel换成了输入流… 话不多说,上代码: //wb ...
* @param multipartFile multipartFile * @return InputStream * @throws IOException IOException public static InputStream parseInputStream(MultipartFile multip public static InputStream workbookConvertorStream(SXSSFWorkbook workbook) { InputStream in = null; //临时缓冲区 ByteArrayOutputStream out = new ByteArrayOutputStream();
package com.jd.ibdreport.service.approta; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.
InputStream is = new ByteArrayInputStream(HSSFWorkbook.getBytes()); 获取输入流后上传服务器。文件是上传成功,但是文件下载后打开会提示文件已损坏。 正确的解决方法(红色涂改... 君且信步登天路,莫惜玩泥孩童时!对于一个爱写代码的人来说,坚持写代码是最好的诠释。我会努力写代码的,也希望我的分享能给你们带来帮助,我觉得这就是我努力的意义,不仅你们收获到了知识,我也看到了自已的进步! 03-30 1. 使用Apache POI库 Apache POI是一个Java库,可以处理Microsoft Office格式的文件,包括Excel。如果你的实体类是基于JavaBean规范的,那么可以使用Apache POI来导出Excel文件。 首先,你需要将实体类的属性与Excel表格中的列一一对应,定义一个数据模型。然后,使用Apache POI的API将数据写入Excel文件中。 以下是一个基于Apache POI的示例代码: ```java public void exportExcel(List<Book> bookList, OutputStream outputStream) { HSSFWorkbook workbook = new HSSFWorkbook(); HSSFSheet sheet = workbook.createSheet("Book List"); // 创建表头 HSSFRow headerRow = sheet.createRow(0); headerRow.createCell(0).setCellValue("Book ID"); headerRow.createCell(1).setCellValue("Title"); headerRow.createCell(2).setCellValue("Author"); headerRow.createCell(3).setCellValue("Price"); // 填充数据 int rowNum = 1; for (Book book : bookList) { HSSFRow row = sheet.createRow(rowNum++); row.createCell(0).setCellValue(book.getId()); row.createCell(1).setCellValue(book.getTitle()); row.createCell(2).setCellValue(book.getAuthor()); row.createCell(3).setCellValue(book.getPrice()); // 输出Excel文件 try { workbook.write(outputStream); } catch (IOException e) { e.printStackTrace(); 2. 使用EasyExcel库 EasyExcel是一个基于阿里巴巴开发的Java库,可以方便地导入和导出Excel文件。如果你的实体类是基于Java Bean规范的,那么可以使用EasyExcel来导出Excel文件。 以下是一个基于EasyExcel的示例代码: ```java public void exportExcel(List<Book> bookList, OutputStream outputStream) { List<BookDTO> bookDTOList = bookList.stream().map(BookDTO::new).collect(Collectors.toList()); ExcelWriter excelWriter = EasyExcel.write(outputStream, BookDTO.class).build(); WriteSheet writeSheet = EasyExcel.writerSheet("Book List").build(); excelWriter.write(bookDTOList, writeSheet); excelWriter.finish(); 在这个示例代码中,我们先将Book实体类换为BookDTO数据传输对象,然后使用EasyExcel的API将数据写入Excel文件中。注意,EasyExcel的API比Apache POI更加简洁易用,但是可能会比较耗费内存