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));//还要其他属性