jfinal 临时文件下载(用户下载完成后删除服务器的文件)

本人在使用jfinal做一个项目的时候,需要下载一些临时文件,就是有程序产生,并且被用户下载后就失效的小文件,在使用jfinal的renderFile(file);后,调用 file.delete();发现,文件无法下载,于是找问题

查看jfinal controller的renderFile源码后发现,调用render系列方法后,并没有马上执行render操作,代码如下:


/**
 * Render with file
 */
public void renderFile(String fileName) {
	render = renderFactory.getFileRender(fileName);
}

/**
 * Render with file
 */
public void renderFile(File file) {
	render = renderFactory.getFileRender(file);
}

由此可见,renderFile只不过是产生了一个render对象而已,这样就能解释了,因为调用renderFile后我们把文件删除了,于是就无法下载了,于是继续找,然后找到调用这个方法的地方,发现是在一个叫做ActionHandler的了类里面,找到这个类的handler方法,关键部位代码如下:

Controller controller = action.getControllerClass().newInstance();
controller.init(request, response, urlPara[0]);

if (devMode) {
	boolean isMultipartRequest = ActionReporter.reportCommonRequest(controller, action);
	new ActionInvocation(action, controller).invoke();
	if (isMultipartRequest) ActionReporter.reportMultipartRequest(controller, action);
} else {
	new ActionInvocation(action, controller).invoke();
}

Render render = controller.getRender();
if (render instanceof ActionRender) {
	String actionUrl = ((ActionRender)render).getActionUrl();
	if (target.equals(actionUrl))
		throw new RuntimeException("The forward action url is the same as before.");
	else
		handle(actionUrl, request, response, isHandled);
	return ;
}

if (render == null)
	render = renderFactory.getDefaultRender(action.getViewPath() + action.getMethodName());
  
render.setContext(request, response, action.getViewPath()).render();

我们发现在 new ActionInvocation(action, controller).invoke();后才去执行的render方法,render.setContext(request, response, action.getViewPath()).render();

问题已经找到了,于是我们需要解决,刚开始问群里的时候,大家都是建议使用定时删除,队列的方式来执行,我个人不喜欢这种绕圈子的做法,于是有了方案1

方案1

自己写代码去renderFile,这样就可以避免这个问题了,代码大致如下(基本上是从FileRender类中拷贝而来):

String contentType = getRequest().getServletContext().getMimeType(file.getName());
if (contentType == null) {
    contentType = "application/octet-stream";		// "application/octet-stream";
}


System.out.println(contentType);

getResponse().setContentType(contentType);
getResponse().setContentLength((int) file.length());
OutputStream out = getResponse().getOutputStream();
FileInputStream in = new FileInputStream(file);

try {
    byte[] buf= new byte[1024];

    for(int n;(n = in.read(buf)) != -1;) {
        out.write(buf,0,n);
    }

} finally {
    try {
        in.close();
        out.close();
    } finally {
        file.delete();
        file.deleteOnExit();
    }
}

这种代码解决了问题,但是还是不够好,我相信大部分人也不喜欢这种方式,虽然可以封装一个方法去做这个事情.后来用了一种更好的方式来解决这个问题,而且比较符合jfinal的设计哲学

方案2

自定义render

由于jfinal已经有了FileRender,我们可以直接继承它,我们重写 render方法就好了,这种方法做到了代码重用,个人很喜欢,代码如下:

public class TempFileRender extends FileRender {
  private String fileName;
  private File file;
  public TempFileRender(String fileName) {
      super(fileName);
      this.fileName = fileName;
  }

  public TempFileRender(File file) {
      super(file);
      this.file = file;
  }

  @Override
  public void render() {
      try {
          super.render();
      } finally {

          if(null != fileName) {
              file = new File(fileName);
          }

          if(null != file) {
              file.delete();
              file.deleteOnExit();
          }
      }
  }
}

这样在controller中使用就只需要 render(new TempFileRender(file|fileName))

打完收工

转载于:https://my.oschina.net/0x0001/blog/265765

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JFinal是一款国产的JavaWeb框架,它提供了方便的文件上传功能。在JFinal中,文件上传的流程可以分为四个步骤:引入需要的jar包、创建jsp页面、配置config和编写后台controller处理方法。首先,我们需要引入相关的jar包。然后,创建一个jsp页面,用于用户选择和上传文件。接下来,在config配置中,我们不需要进行xml配置,可以在java类的config类中配置相关信息。最后,在后台controller处理方法中,我们可以通过this.getFile()方法获取上传的文件参数,并进行相应的处理。通过这些步骤,我们可以实现JFinal文件上传功能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [JFinal框架单文件、多文件上传详解](https://blog.csdn.net/alan_liuyue/article/details/79386540)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [JFinal文件上传](https://blog.csdn.net/Lurk_111/article/details/90167554)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值