乐趣区

关于java:获取oss的pdf文件返回文件输出流

获取 oss 的 pdf 文件,返回文件输入流

需要:oss 上存储生成的 pdf 文件,通过存储的 key,返回对应的 PDF 文件输入流

 实现:后端 Java 提供获取 pdf 文件的输入流,前端 vue 将文件流另存为 PDF 文件


接口代码实现:

import java.io.BufferedInputStream;
import java.io.InputStream;
import java.util.Objects;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.aliyun.oss.model.OSSObject;
import com.sisensing.cgm.common.core.utils.ErrUtil;
import com.sisensing.cgm.system.domain.dto.ReportQueryDTO;
import com.sisensing.cgm.system.service.ICgmDownloadService;

import cn.hutool.core.io.IoUtil;
import org.springframework.stereotype.Service;

......

private static final Logger LOGGER = LoggerFactory.getLogger(CgmDownloadServiceServiceImpl.class);

    @Override
    public void getReportFileStream(ReportQueryDTO reportQueryDTO, HttpServletResponse response) {
        // 报告尚未生成 pdf 报告
        ErrUtil.throwIfTrue(StringUtils.isEmpty(reportQueryDTO.getPdfKey()), REPORT_HAS_NOT_PDF,
            String.format("pdfKey 不容许为空"));
        OSSObject ossObject = this.getServiceFactory().getOssService().downloadOssFile(reportQueryDTO.getPdfKey());
        ServletOutputStream out = null;
        if (Objects.nonNull(ossObject)) {InputStream inputStream = ossObject.getObjectContent();
            BufferedInputStream bis = new BufferedInputStream(inputStream);
            int buffer = 1024 * 10;
            byte[] data = new byte[buffer];
            try {response.setContentType("application/pdf");
                // 文件名能够任意指定
                long timeId = System.currentTimeMillis();
                response.setHeader("Content-Disposition", "attachment;fileName=" + timeId + ".pdf");
                int read;
                out = response.getOutputStream();
                while ((read = bis.read(data)) != -1) {out.write(data, 0, read);
                }
                out.flush();} catch (Exception ex) {IoUtil.close(out);
                LOGGER.error("下载 PDF 报告失败", ex);
                ErrUtil.throwNow(GET_REPORT_STREAM_FAIL, String.format("pdfKey 为 [%s]", reportQueryDTO.getPdfKey()));
            } finally {IoUtil.close(ossObject);
            }
        }
    }
    
    ......

     @Autowired
    private OSSClient ossClient;

    @Autowired
    private OSSProperties ossProperties;
    
    /**
     * 下载 oss 存储的文件对象
     *
     * @param key
     * @return
     */
    public OSSObject downloadOssFile(String key) {return ossClient.getObject(ossProperties.getBucketName(), key);
    }


ps: 因为前端页面申请的形式是 POST,若应用以下的形式将文件输入流保留

/** 下载操作 */
    handleDownload(row) {if (row.pdfKey) {// 已生成 pdf
          const param = {pdfKey : row.pdfKey};
        getReportStream(param).then(res => {if(!res) return
          let url = window.URL.createObjectURL(new Blob([res]), {type: 'application/pdf'})
          let link = document.createElement('a')
          link.style.display = 'none'
          link.href = url
          link.setAttribute('download', `xxxx 报告.pdf`)
          document.body.appendChild(link)
          link.click()
          document.body.removeChild(link)
          URL.revokeObjectURL(link.href) // 开释 URL 对象
        })
      } else {this.$message('报告正在生成中请稍后')
      }
    }



// 获取报告文件输入流
export function getReportStream(data) {
  return request({
    url: `xxx/xxx/pdf/stream`,
    method: 'post',
    data: data,
    responseType: 'blob',
  })
}


实现成果截图:

① blob 返回的文件输入流,console 打印

② swagger 接口申请返回后果

③ 下载的前端入口

④ 下载胜利的 pdf 文件,在浏览器的左下角显示对应的文件

退出移动版