代码改变世界

[转] JAVA中读取网络中的图片资源导入到EXCEL中

2017-09-05 12:02  faunjoe88  阅读(2392)  评论(0编辑  收藏  举报

需求

导出人员的信息并且加上人员的照片至EXCEL中

完整的代码

//创建一个表格
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();

//需要导出的人员信息
List<StaffBO> boList =staffService.findStaffList(searchBO);
if(boList != null && boList.size() >0)
{
    //一定要放在循环外,只能声明一次
    HSSFPatriarch patriarch = sheet.createDrawingPatriarch();     
    for(int i=0; i<boList.size(); i++)
    {
        HSSFRow dataRow = sheet.createRow(i+1);//数据行
        HSSFCell dataCell0 = dataRow.createCell(0);//每行的第一列存放照片
        drawPictureInfoExcel(wb,patriarch,i+1,obj.getLaborStore().getPhoto());//i+1代表当前的行
    }

}

// 关于HSSFClientAnchor(dx1,dy1,dx2,dy2,col1,row1,col2,row2)的参数,有必要在这里说明一下:
// dx1:起始单元格的x偏移量,
// dy1:起始单元格的y偏移量,
// dx2:终止单元格的x偏移量,
// dy2:终止单元格的y偏移量,
// col1:起始单元格列序号,从0开始计算;
// row1:起始单元格行序号,从0开始计算,
// col2:终止单元格列序号,从0开始计算;
// row2:终止单元格行序号,从0开始计算,
private void drawPictureInfoExcel(HSSFWorkbook wb,HSSFPatriarch patriarch,int rowIndex,String pictureId)
{
//rowIndex代表当前行
    try {
        String pictureUrl = null;
        if(StringUtils.isNotBlank(pictureId)) {
            UploadFile pictureFile = uploadFileService.get(pictureId);
            if(pictureFile != null) {
                pictureUrl = pictureFile.getPath();//获取人员照片的地址
            }
            logger.info("人员照片地址为:"+pictureUrl);
        }
        if(StringUtils.isNotBlank(pictureUrl)) {
                    URL url = new URL(pictureUrl);  
                    //打开链接  
                    HttpURLConnection conn = (HttpURLConnection)url.openConnection();  
                    //设置请求方式为"GET"  
                    conn.setRequestMethod("GET");  
                    //超时响应时间为5秒  
                    conn.setConnectTimeout(5 * 1000);  
                    //通过输入流获取图片数据  
                    InputStream inStream = conn.getInputStream();  
                    //得到图片的二进制数据,以二进制封装得到数据,具有通用性  
                    byte[] data = readInputStream(inStream);  
                    //anchor主要用于设置图片的属性  
                    HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 1023, 250,(short) 0, rowIndex, (short) 0, rowIndex);     
                    //Sets the anchor type (图片在单元格的位置)
                    //0 = Move and size with Cells, 2 = Move but don't size with cells, 3 = Don't move or size with cells.
                    anchor.setAnchorType(0);     
                    patriarch.createPicture(anchor, wb.addPicture(data, HSSFWorkbook.PICTURE_TYPE_JPEG));   
        }
    } catch (IOException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }     
}

导出的结果如下:

解决说明

1. 获取网络中的图片资源

百度了一下,一共找到两种

第一种:

//pictureUrl是人员照片的地址
URL url = new URL(pictureUrl);
BufferedImage bufferImg = ImageIO.read(url);    
ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
ImageIO.write(bufferImg, "jpg", byteArrayOut);  
byte[] data = byteArrayOut.toByteArray();
//最终导入时所需要的图片要转换为byte[]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

但是发现一个问题,在本地测试是可以正常导出的,到了服务器中就不能导出,记录了一下导出时的日志,发现图片的地址是这样的

http://www.xxx.cn:80/appfile//modules/apphr/staff/1481865941995.png
  • 1
  • 1

多了一个端口号,去掉端口号时可以正常导出的,把地址直接黏贴到浏览器中也是可以访问的,不得其解,问了一下别人也没得出原因

第二种(本地和服务器都可以):

//java.net.URL
//java.net.HttpURLConnection;
URL url = new URL(pictureUrl);  
//打开链接  
HttpURLConnection conn = (HttpURLConnection)url.openConnection();  
//设置请求方式为"GET"  
conn.setRequestMethod("GET");  
//超时响应时间为5秒  
conn.setConnectTimeout(5 * 1000);  
//通过输入流获取图片数据  
InputStream inStream = conn.getInputStream();  
//得到图片的二进制数据,以二进制封装得到数据,具有通用性  
byte[] data = readInputStream(inStream);  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
private static byte[] readInputStream(InputStream inStream) throws Exception{  
    ByteArrayOutputStream outStream = new ByteArrayOutputStream();  
    //创建一个Buffer字符串  
    byte[] buffer = new byte[1024];  
    //每次读取的字符串长度,如果为-1,代表全部读取完毕  
    int len = 0;  
    //使用一个输入流从buffer里把数据读取出来  
    while( (len=inStream.read(buffer)) != -1 ){  
        //用输出流往buffer里写入数据,中间参数代表从哪个位置开始读,len代表读取的长度  
        outStream.write(buffer, 0, len);  
    }  
    //关闭输入流  
    inStream.close();  
    //把outStream里的数据写入内存  
    return outStream.toByteArray();  
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

2. 导入到EXCEL中

导出使用的时POI,主要用到两个类:

HSSFPatriarch(负责再excel中创建图片)、HSSFClientAnchor(负责图片再excel中的位置)
  • 1
  • 1

代码如下:


//创建一个工作簿
HSSFWorkbook wb = new HSSFWorkbook();
//创建一个表格
HSSFSheet sheet = wb.createSheet();
//一定要放在循环外,只能声明一次 
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();   
for(int i=0; ...; i++)
{
    //调用插入图片到excel的方法
    drawPictureInfoExcel(wb,patriarch,i,"图片地址");
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
//rowIndex代表的是当前的行标
private void drawPictureInfoExcel(HSSFWorkbook wb,HSSFPatriarch patriarch,int rowIndex,String pictureId)
{
    try {
        //anchor主要用于设置图片的属性  
        HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 1023, 250,(short) 0, rowIndex, (short) 0, rowIndex); 
        //Sets the anchor type (图片在单元格的位置)
        //0 = Move and size with Cells, 2 = Move but don't size with cells, 3 = Don't move or size with cells.
        anchor.setAnchorType(0);     
        patriarch.createPicture(anchor, wb.addPicture(data, HSSFWorkbook.PICTURE_TYPE_JPEG));   
    } catch (IOException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }     
}