1、需求背景:
我司内部大大小小的团队非常多,每个团队又有自己专属的开发小队,业务关系,经常需要用到其他团队的接口,例如需要某团队开发的一个接口,这个接口返回一个文件流,我想直接在前端打开或者下载。
2、实现方式:
扩展JFinal的Render类
3、代码:
import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import com.jfinal.kit.LogKit; import com.jfinal.kit.StrKit; import com.jfinal.render.Render; import com.jfinal.render.RenderException; public class ByteRender extends Render { private String fileName;// 下载名称 private byte[] fileByte; //前端试图展示的文件类型,例如想通过浏览器直接打开为pdf类型 private FileType fileType = FileType.PDF; //浏览器直接试图查看和下载两种方式 private RenderType renderType = RenderType.VIEW;// 默认类型 private ServletOutputStream outputStream; public ByteRender() { } public void render() { if (validate() == false) { throw new RenderException("请检查ByteRender属性值是否为空"); } if (renderType == RenderType.DOWNLOAD) { response.setHeader("Content-Disposition", getFilename(request)); } response.setHeader("Pragma", "no-cache"); response.setHeader("Cache-Control", "no-cache"); response.setHeader("Accept-Ranges", "bytes"); response.setDateHeader("Expires", 0); response.setContentType(fileType.contentType); try { this.outputStream = response.getOutputStream(); switch (fileType) { case JPG: renderImage(); case PDF: // 暂时只支持pdf renderPdf(); } } catch (IOException e) { LogKit.error(e.getMessage(), e); } catch (Exception e) { LogKit.error(e.getMessage(), e); } finally { if (outputStream != null) { try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } void renderPdf() throws IOException { outputStream.write(fileByte); outputStream.flush(); outputStream.close(); } void renderImage() { //这里自定义扩展 } /** * 文件下载名称 */ private String getFilename(HttpServletRequest request) { try { String agent = request.getHeader("USER-AGENT"); if (agent.toLowerCase().indexOf("firefox") > 0) { fileName = new String(fileName.getBytes("utf-8"), "ISO8859-1"); } else { fileName = URLEncoder.encode(fileName, "UTF-8"); } } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return "attachment; filename=" + fileName + "." + fileType.suffix; } private boolean validate() { if (renderType == null || fileType == null) { return false; } // 如果是下载,需要传入下载的名称 if (renderType == RenderType.DOWNLOAD) { if (StrKit.isBlank(fileName)) { return false; } } if (fileByte == null || fileByte.length == 0) { return false; } return true; } public static ByteRender create() { return new ByteRender(); } public static ByteRender create(byte[] fileByte) { return create().setFileByte(fileByte); } public ByteRender setFileName(String fileName) { this.fileName = fileName; return this; } public ByteRender setFileByte(byte[] fileByte) { this.fileByte = fileByte; return this; } public ByteRender setFileType(FileType fileType) { this.fileType = fileType; return this; } public void setRenderType(RenderType renderType) { this.renderType = renderType; } public enum FileType { PDF("application/pdf", "pdf"), JPG("image/jpeg", "jpg"); public String contentType; public String suffix; FileType(String contentType, String suffix) { this.contentType = contentType; this.suffix = suffix; } } public enum RenderType { // 下载和视图显示 DOWNLOAD, VIEW } @Override public String toString() { return "ByteRender [fileName=" + fileName + ", fileByte[length]=" + (fileByte == null ? "null" : fileByte.length) + ", fileType=" + fileType + ", renderType=" + renderType + "]"; } }
4、使用方式:
byte[] bytes = data.toString().getBytes(ISO);//来自任何地方 默认方式: render(ByteRender.create(bytes)); 或者自定义: render(ByteRender.create(bytes).setFileType(ByteRender.FileType.JPG));//还要其他属性