0


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

目录

需求:

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

准备:

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

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

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

文件、流之间的转换

MultipartFile 转 inputstream(输入流)

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

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

ByteArrayOutputStream outputStream =newByteArrayOutputStream();InputStream inputStream2 =newByteArrayInputStream(outputStream.toByteArray());

inputstream (输入流)转 ByteArrayOutputStream

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

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

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

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

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

//转换为pdf 后的输出流ByteArrayOutputStream outputStream =newByteArrayOutputStream();//原文件byte[] byteArr=file.getBytes();InputStream inputStream =newByteArrayInputStream(byteArr);//要转为pdf 文档Word2PdfUtil.convert2PdfStream(inputStream,outputStream);//输出流转输入流ByteArrayOutputStream baosPdf =(ByteArrayOutputStream) outputStream ;InputStream inputStream2 =newByteArrayInputStream(baosPdf.toByteArray());//inputStream 只能用来读取一次  所以进行copy一个新的 用来生成摘要InputStream inputStream3 =newByteArrayInputStream(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")publicBaseVo<Contract>uploadWordFile(HttpServletRequest request,MultipartFile file,HttpServletResponse response){long startTimeTotal =System.currentTimeMillis();BaseVo<Contract> baseVo =newBaseVo<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 =newByteArrayInputStream(byteArr);InputStream inputStream2 =newByteArrayInputStream(byteArr);
                        url =CephUtils.uploadInputStreamReturnUrl("/"+Constants.CEPH_BUCK_NAME, fileName, inputStream);//生成文档hash 摘要
                        hash =FileHahUtil.hashAbstractByInputStream(inputStream2);}else{ByteArrayOutputStream outputStream =newByteArrayOutputStream();byte[] byteArr=file.getBytes();InputStream inputStream =newByteArrayInputStream(byteArr);//要转为pdf 文档Word2PdfUtil.convert2PdfStream(inputStream,outputStream);ByteArrayOutputStream baosPdf =(ByteArrayOutputStream) outputStream ;InputStream inputStream2 =newByteArrayInputStream(baosPdf.toByteArray());//inputStream 只能用来读取一次  所以进行copy一个新的 用来生成摘要InputStream inputStream3 =newByteArrayInputStream(baosPdf.toByteArray());//生成文档hash 摘要
                        hash =FileHahUtil.hashAbstractByInputStream(inputStream3);
                        url = fileService.uploadFileByInputStream(inputStream2,fileName);
                        baosPdf.close();
                        inputStream2.close();
                        outputStream.close();}if(StringUtils.isNotEmpty(url)){// 保存合同信息 到数据库Contract contract =newContract();//随机字符串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.SUCCESS_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值
     */publicstaticStringhashAbstractByInputStream(InputStream fis)throwsException{String sha256 =null;try{MessageDigest md =MessageDigest.getInstance("SHA-256");byte buffer[]=newbyte[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();thrownewException("生成文件hash值失败");}finally{try{if(fis !=null){
                    fis.close();}}catch(IOException e){
                e.printStackTrace();}}return sha256;}

docx或doc转pdf

publicstaticvoidconvert2PdfStream(InputStream inputStream,ByteArrayOutputStream outputStream){if(!getLicense()){// 验证License 若不验证则转化出的pdf文档会有水印产生return;}try{long old =System.currentTimeMillis();Document doc =newDocument(inputStream);//insertWatermarkText(doc, "测试水印"); //添加水印PdfSaveOptions pdfSaveOptions =newPdfSaveOptions();
            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
     */publicstaticStringuploadInputStreamReturnUrl(String bucketName,String fileName,InputStream input){//        String path = bucketName + timeSuffix();PutObjectResult putObjectResult = conn.putObject(bucketName, fileName, input,newObjectMetadata());String cephUrl = ENDPOINT + bucketName +"/"+ fileName;return cephUrl;}
标签: java spring boot 后端

本文转载自: https://blog.csdn.net/xuxu_study/article/details/129992752
版权归原作者 需许徐徐 所有, 如有侵权,请联系我们删除。

“outputStream(输出流)转inputstream(输入流)以及输入流如何复用”的评论:

还没有评论