1、背景说明

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

2、所需依赖包

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

org.apache.poi

poi

3.14

org.apache.poi

poi-ooxml

3.14

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的描述:

java 差两个表 java比较两个excel的不同_java区分不同的excel

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

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

java 差两个表 java比较两个excel的不同_java区分不同的excel

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

5、总结

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

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