outputStream(输出流)转inputstream(输入流)以及输入流如何复用

outputStream(输出流)转inputstream(输入流)以及输入流如何复用

需求:

通过MultipartFile 上传文件到文件服务器,上传前要把文件转为pdf格式进行上传,并生成文件摘要用来验证服务器中的文件是否被篡改。

准备:

需要涉及到 inputstream(输入流)或outputStream(输出流)要使用两次 。
一、如果该文件本身就是pdf格式则直接进行上传。第一次是通过输入流去上传文件;第二次是通过输入流去生成文件摘要。

二、如果该文件不是pdf则需要工具类把文件转为pdf再上传。转pdf的工具类 返回的为outputStream(输出流)。上传的工具类以及生成摘要的工具类则需要inputstream(输入流)。
则需要把输出流进行转化变为输入流,然后再第一次是通过输入流去上传文件;第二次是通过输入流去生成文件摘要

注:流读过一次就不能再读了,而InputStream对象本身不能复制

文件、流之间的转换

MultipartFile 转 inputstream(输入流)

 byte [] byteArr=file.getBytes();
 InputStream inputStream = new ByteArrayInputStream(byteArr);

outputStream(输出流)转为 inputstream(输入流)

 ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
 InputStream inputStream2 = new ByteArrayInputStream(outputStream.toByteArray());

inputstream (输入流)转 ByteArrayOutputStream

 //InputStream 转 ByteArrayOutputStream
 //获取到一个inputstream后,可能要多次利用它进行read的操作。由于流读过一次就不能再读了,而InputStream对象本身不能复制,而且它也没有实现Cloneable接口  
 public static ByteArrayOutputStream cloneInputStream(InputStream input) {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len;
            while ((len = input.read(buffer)) > -1) {
                baos.write(buffer, 0, len);
            }
            baos.flush();
            return baos;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

MultipartFile 文件直接转输入流上传和生成摘要

通过file 转字节数组,因为流不能重复读,所以要new成两个输入流。

 //获取并生成以pdf为后缀的文件名称
  String fileName = StringUtils.substringBeforeLast(originalFilename,".");
   fileName = fileName +".pdf";
   //如果上传的为pdf 则直接进行上传 不需要转换
   if(originalFilename.endsWith(".pdf")){
       //文件转字节数组
       byte [] byteArr=file.getBytes();
       //输入流1
       InputStream inputStream = new ByteArrayInputStream(byteArr);
       //输入流2
       InputStream inputStream2 = new ByteArrayInputStream(byteArr);
       //文件上传
       url = CephUtils.uploadInputStreamReturnUrl("/" + Constants.CEPH_BUCK_NAME, fileName, inputStream);
       //生成文档hash 摘要
       hash = FileHahUtil.hashAbstractByInputStream(inputStream2);
    }

MultipartFile 文件需要转为pdf 再进行上传和生成摘要

 //转换为pdf 后的输出流
 ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
 //原文件
 byte [] byteArr=file.getBytes();
  InputStream inputStream = new ByteArrayInputStream(byteArr);
  //要转为pdf 文档
  Word2PdfUtil.convert2PdfStream(inputStream,outputStream);
  //输出流转输入流
  ByteArrayOutputStream baosPdf = (ByteArrayOutputStream) outputStream ;
  InputStream inputStream2 = new ByteArrayInputStream(baosPdf.toByteArray());
  //inputStream 只能用来读取一次  所以进行copy一个新的 用来生成摘要
  InputStream inputStream3 = new ByteArrayInputStream(baosPdf.toByteArray());
  //生成文档hash 摘要
  hash = FileHahUtil.hashAbstractByInputStream(inputStream3);
  //上传文件
  url = fileService.uploadFileByInputStream(inputStream2,fileName);

文件上传源码

 //文件上传(文档转pdf)
    @ApiOperation(value = "文件上传(文档转pdf)", produces = "application/json")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "文件上传(文档转pdf)")})
    @PostMapping(value = "/uploadWordFile")
    public BaseVo<Contract> uploadWordFile(HttpServletRequest request, MultipartFile file, HttpServletResponse response){
        long startTimeTotal = System.currentTimeMillis();
        BaseVo<Contract> baseVo = new BaseVo<Contract>();
        baseVo.setCodeMessage(CodeConstant.FAILURE_CODE);
        try {
            if(null != file){
                String originalFilename = file.getOriginalFilename();
                //文件上传后返回的地址
                String url = "";
                //文件摘要的hash值
                String hash = "";
                if (!originalFilename.endsWith(".docx") && !originalFilename.endsWith(".doc") && !originalFilename.endsWith(".pdf")) {
                    //上传的文件格式不支持
                    baseVo.setMessage("暂不支持当前文件格式上传!");
                }else {
                    //生成新的文件名称
                    String fileName = StringUtils.substringBeforeLast(originalFilename,".");
                    fileName = fileName +".pdf";
                    //如果上传的为pdf 则直接进行上传 不需要转换
                    if(originalFilename.endsWith(".pdf")){
                        byte [] byteArr=file.getBytes();
                        InputStream inputStream = new ByteArrayInputStream(byteArr);
                        InputStream inputStream2 = new ByteArrayInputStream(byteArr);
                        url = CephUtils.uploadInputStreamReturnUrl("/" + Constants.CEPH_BUCK_NAME, fileName, inputStream);
                        //生成文档hash 摘要
                        hash = FileHahUtil.hashAbstractByInputStream(inputStream2);
                    }else {
                        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                        byte [] byteArr=file.getBytes();
                        InputStream inputStream = new ByteArrayInputStream(byteArr);
                        //要转为pdf 文档
                        Word2PdfUtil.convert2PdfStream(inputStream,outputStream);
                        ByteArrayOutputStream baosPdf = (ByteArrayOutputStream) outputStream ;
                        InputStream inputStream2 = new ByteArrayInputStream(baosPdf.toByteArray());
                        //inputStream 只能用来读取一次  所以进行copy一个新的 用来生成摘要
                        InputStream inputStream3 = new ByteArrayInputStream(baosPdf.toByteArray());
                        //生成文档hash 摘要
                        hash = FileHahUtil.hashAbstractByInputStream(inputStream3);
                        url = fileService.uploadFileByInputStream(inputStream2,fileName);
                        baosPdf.close();
                        inputStream2.close();
                        outputStream.close();
                    }
                    if(StringUtils.isNotEmpty(url)){
                        // 保存合同信息 到数据库
                        Contract contract = new Contract();
                        //随机字符串
                        String str = StringUtils.replace(UUID.randomUUID().toString(), "-", "");
                        contract.setCode(CodeGenerator.getLongCode(str));
                        contract.setContractUrl(url);
                        contract.setName(fileName);
                        contract.setHashCode(hash);
                        contractService.saveOrUpdate(contract);
                        //返回合同信息
                        baseVo.setData(contract);
                        baseVo.setCodeMessage(CodeConstant.SU***ESS_CODE);
                    }
                }

            }
        }catch (Exception e){
            e.printStackTrace();
            MeUtils.info("uploadFile error",e);
        }
        long endTimeTotal = System.currentTimeMillis();
        MeUtils.info("uploadFile total time:" + (endTimeTotal - startTimeTotal));
        return baseVo;
    }

生成文件摘要用的是文件hash 摘要算法中的SHA-256,docx或doc转pdf用的是aspose 中提供的方法,文件上传用的Ceph分布式文件系统中的。这里暂时不详细介绍,只贴一些代码。后面再出详细文档,以及开发中遇到的坑。

文件hash 摘要算法
 /**
     * 生成文件hashCode值
     */
    public static String hashAbstractByInputStream(InputStream fis) throws Exception {
        String sha256 = null;
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            byte buffer[] = new byte[1024];
            int length = -1;
            while ((length = fis.read(buffer, 0, 1024)) != -1) {
                md.update(buffer, 0, length);
            }
            byte[] digest = md.digest();
            sha256 = byte2hexLower(digest);
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("生成文件hash值失败");
        } finally {
            try {
                if (fis != null) {
                    fis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return sha256;
    }
docx或doc转pdf
public static void convert2PdfStream(InputStream inputStream, ByteArrayOutputStream outputStream) {
        if (!getLicense()) { // 验证License 若不验证则转化出的pdf文档会有水印产生
            return;
        }
        try {
            long old = System.currentTimeMillis();
            Document doc = new Document(inputStream);
            //insertWatermarkText(doc, "测试水印"); //添加水印
            PdfSaveOptions pdfSaveOptions = new PdfSaveOptions();
            pdfSaveOptions.setSaveFormat(SaveFormat.PDF);
            // 设置3级doc书签需要保存到pdf的heading中
            pdfSaveOptions.getOutlineOptions().setHeadingsOutlineLevels(3);
            // 设置pdf中默认展开1级
            pdfSaveOptions.getOutlineOptions().setExpandedOutlineLevels(1);
            //doc.save(outputStream, pdfSaveOptions);
            // 全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF,EPUB, XPS, SWF 相互转换
            doc.save(outputStream, SaveFormat.PDF);
            long now = System.currentTimeMillis();
            System.out.println("共耗时:" + ((now - old) / 1000.0) + "秒"); // 转化用时

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

文件上传
 /**
     * 上传InputStream文件
     *
     * @param bucketName
     * @param fileName
     * @param input
     */
    public static String uploadInputStreamReturnUrl(String bucketName, String fileName, InputStream input) {
//        String path = bucketName + timeSuffix();
        PutObjectResult putObjectResult = conn.putObject(bucketName, fileName, input, new ObjectMetadata());
        String cephUrl = ENDPOINT + bucketName + "/" + fileName;
        return cephUrl;
    }
转载请说明出处内容投诉
CSS教程_站长资源网 » outputStream(输出流)转inputstream(输入流)以及输入流如何复用

发表评论

欢迎 访客 发表评论

一个令你着迷的主题!

查看演示 官网购买