根据html代码生成word文件

需求是前端传css和body过来,后端通过字符串拼接将数据拼成html的字符串,然后需要将这个html字符串转换为word的doc文件,并交由前端进行下载。下载方式为手机(通常是微信)扫描二维码,访问后台API或者是文件的物理路径实现下载。

首先尝试的是通过POI的方式,将html转成doc,然后返回给前端一个流,实现下载功能。

/**
     * html转word
     * @throws IOException 
     */
    public static void htmlToDoc(String html,String fileName,HttpServletResponse response,HttpServletRequest request) throws IOException {
        byte b[] = html.getBytes("utf-8");  //这里是必须要设置编码的,不然导出中文就会乱码。
        ByteArrayInputStream bais = new ByteArrayInputStream(b);//将字节数组包装到流中  
        /*
         * 关键地方
         * 生成word格式
         */
        POIFSFileSystem poifs = new POIFSFileSystem();  
        DirectoryEntry directory = poifs.getRoot();  
        DocumentEntry documentEntry = directory.createDocument("WordDocument", bais); 
        //输出文件
        request.setCharacterEncoding("utf-8");  
//      response.setContentType("application/msword");//导出word格式
        response.addHeader("Content-Disposition", "attachment;filename=" +
                 new String( (fileName + ".doc").getBytes(),  
                         "iso-8859-1"));

        OutputStream ostream = response.getOutputStream(); 
        poifs.writeFilesystem(ostream);  
        bais.close();  
        ostream.close(); 
    }

通过上述代码可以实现下载的功能。

在测试时发现了问题,Android手机可以弹出下载,但是手机端提示打开文件失败,但是发送文件到电脑端,可以正常打开。ios无法弹出下载。

后来找到的原因,是因为手机端解析doc文件的时候将它识别成了html文件,但是电脑端的word可以正常的解析。还有种说法是由于流或者其他浏览页面未关闭,导致了文件写入属性不完整导致的,这个有待考究。ios端问题不详。

之后决定换一种思路:将生成的doc文件存在阿里云的OSS上,然后返回文件在OSS上的物理路径给前端,达到下载的目的。

阿里云OSS上传官方文档

上传Byte数组
以下代码用于上传Byte数组:

// Endpoint以杭州为例,其它Region请按实际情况填写。
String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
// 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建RAM账号。
String accessKeyId = "<yourAccessKeyId>";
String accessKeySecret = "<yourAccessKeySecret>";

// 创建OSSClient实例。
OSSClient ossClient = new OSSClient(endpoint, accessKeyId,accessKeySecret);

// 上传Byte数组。
byte[] content = "Hello OSS".getBytes();
ossClient.putObject("<yourBucketName>", "<yourObjectName>", new ByteArrayInputStream(content));

// 关闭OSSClient。
ossClient.shutdown();

我写的文档

          String url="";
          // 生成临时文件名称
          fileName = fileName+".doc";
          String content =html;
          String bucketName="shidu-temp";
          String fileDomain="http://shidu-temp.oss-cn-hangzhou.aliyuncs.com/";
          String key="words/"+fileName;
          url=AliossUtil.uploadByteArray(fileDomain, bucketName, key, content);

          return url;
    /**
     * 字节数组上传
     *
     * @param fileDomain 文件域名
     * @param bucketName bucket名称
     * @param key 文件key
     * @param content html字符串
     *
     * @return
     */
    public static String uploadByteArray(String fileDomain,String bucketName,String key,String content){

        OSSClient ossClient = new OSSClient(END_POINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);

        // 上传Byte数组。
        byte[] b = content.getBytes();
        ossClient.putObject(bucketName, key, new ByteArrayInputStream(b));
        // 关闭OSSClient。
        ossClient.shutdown();

        return fileDomain+key;
    }

以上代码实现的所需功能,在Android的微信中可以正常扫码下载,因为ios并不支持弹出下载窗口,所以只是将文件的实际物理路径解析成了doc文件,直接打开了,也算是达到了需求。

发表评论

电子邮件地址不会被公开。 必填项已用*标注