获取 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 文件,在浏览器的左下角显示对应的文件