Webwork 实现文件上传下载代码详解_javascript技巧
本文主要从三个方面给大家介绍webwork文件上传下载知识,包括以下三个方面:
1. 包装 Request 请求
2. 获取文件上传的解析类
3. 项目实战配置和使用
Web上传和下载应该是很普遍的一个需求,无论是小型网站还是大并发访问的交易网站。WebWork 当然也提供了很友好的拦截器来实现对文件的上传,让我们可以专注与业务逻辑的设计和实现,在实现上传和下载时顺便关注了下框架上传下载的实现。
1. 包装 Request 请求
•每次客户端请求 Action 时,都会调用 WebWork 调度类 ServletDispatcher.service()方法。
具体过程请参照:详解Webwork中Action 调用的方法
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException { try { if (encoding != null) { try { request.setCharacterEncoding(encoding); } catch (Exception localException) { } } if (locale != null) { response.setLocale(locale); } if (this.paramsWorkaroundEnabled) { request.getParameter("foo"); } request = wrapRequest(request); //封装 request请求 serviceAction(request, response, getNameSpace(request), getActionName(request), getRequestMap(request), getParameterMap(request), getSessionMap(request), getApplicationMap()); } catch (IOException e) { String message = "Could not wrap servlet request with MultipartRequestWrapper!"; log.error(message, e); sendError(request, response, 500, new ServletException(message, e)); } }
先来看看 wrapRequest 方法做了什么:
protected HttpServletRequest wrapRequest(HttpServletRequest request) throws IOException { if ((request instanceof MultiPartRequestWrapper)) { return request; } if (MultiPartRequest.isMultiPart(request)) { request = new MultiPartRequestWrapper(request, getSaveDir(), getMaxSize()); } return request; }
• 首先判断了传进来的 request 是不是已经被封装好的 MultiPartRequestWrapper,如果是就直接返回。
• 否则再判断 request 的头信息里面的 ContentType 是不是多类型参数 (multipart/formdata)的请求,如果是就把 request 包装成 WebWork 自己的 MultiPartRequestWrapper 类型,该类型继承HttpServletRequestWrapper 。
MultiPartRequest.isMultiPart() 方法实现如下:
public static boolean isMultiPart(HttpServletRequest request){ String content_type = request.getHeader("Content-Type"); return content_type != null && content_type.startsWith("multipart/form-data"); }
•在 webwork.properties 里面配置文件的临时存储目录、还有最大上传大小,其实就是在这个时候起到作用的。
•创建 MultiPartRequestWrapper 对象的时候传入的参数是由 getSaveDir() 和 getMaxSize() 方 法 获 得 的 。
•在方法里会查找配置里面的 webwork.multipart.saveDir、 webwork.multipart.maxSize 属性,找到则使用该属性指定的临时目录和上传的最大内容,没找到就使用环境的临时目录。
具体实现如下:
protected String getSaveDir() { String saveDir = Configuration.getString("webwork.multipart.saveDir").trim(); if (saveDir.equals("")) { File tempdir = (File) getServletConfig().getServletContext().getAttribute("javax.servlet.context.tempdir"); log.info("Unable to find 'webwork.multipart.saveDir' property setting. Defaulting to javax.servlet.context.tempdir"); if (tempdir != null) { saveDir = tempdir.toString(); } } else { File multipartSaveDir = new File(saveDir); if (!multipartSaveDir.exists()) { multipartSaveDir.mkdir(); } } if (log.isDebugEnabled()) { log.debug("saveDir=" + saveDir); } return saveDir; }
2. 获取文件上传的解析类
再来看一下 MultiPartRequestWrapper 的构造函数使如何包装 request 的:
public MultiPartRequestWrapper(HttpServletRequest request, String saveDir, int maxSize) throws IOException { super(request); if ((request instanceof MultiPartRequest)) { this.multi = ((MultiPartRequest) request); } else { String parser = ""; parser = Configuration.getString("webwork.multipart.parser"); if (parser.equals("")) { log.warn("Property webwork.multipart.parser not set. Using com.opensymphony.webwork.dispatcher.multipart.PellMultiPartRequest"); parser = "com.opensymphony.webwork.dispatcher.multipart.PellMultiPartRequest"; } else if (parser.equals("pell")) { parser = "com.opensymphony.webwork.dispatcher.multipart.PellMultiPartRequest"; } else if (parser.equals("cos")) { parser = "com.opensymphony.webwork.dispatcher.multipart.CosMultiPartRequest"; } else if (parser.equals("jakarta")) { parser = "com.opensymphony.webwork.dispatcher.multipart.JakartaMultiPartRequest"; } try { Class baseClazz = MultiPartRequest.class; Class clazz = Class.forName(parser); if (!baseClazz.isAssignableFrom(clazz)) { addError("Class '" + parser + "' does not extend MultiPartRequest"); return; } Constructor ctor = clazz.getDeclaredConstructor(new Class[] { Class.forName("javax.servlet.http.HttpServletRequest"), String.class, Integer.TYPE }); Object[] parms = { request, saveDir, new Integer(maxSize) }; this.multi = ((MultiPartRequest) ctor.newInstance(parms)); } catch (ClassNotFoundException e) { addError("Class: " + parser + " not found."); } catch (NoSuchMethodException e) { addError("Constructor error for " + parser + ": " + e); } catch (InstantiationException e) { addError("Error instantiating " + parser + ": " + e); } catch (IllegalAccessException e) { addError("Access errror for " + parser + ": " + e); } catch (InvocationTargetException e) { addError(e.getTargetException().toString()); } } }
• 首先它判断了传入的 request 是不是 MultiPartRequest 抽象类的子类,如果是就直接把自身的 MultiPartRequest 类型的变量引用 request。
• 否则读取 WebWork 配置 的webwork.multipart.parser 属性,该属性决定 Webwork 内部用什么实现文件上传。 如果没有指定,则默认使用 PellMultiPartRequest 的实现。
•找到配置的类后,WebWork 通过 Java 反射创建该类的实例。所有支持的类都是从 MultiPartRequest 继承而来,创建该实例后向上转型,并赋予 MultiPartRequestWrapper 的成员multi。
• WebWork 的文件上传封装了几种通用的 FileUpload lib,并不是自己实现的。
•它包括了pell,cos,apache common 三种实现,WebWork 对这三个包进行封装,提供了一 个通用的访问接口 MultiPartRequest,细节实现分别是 PellMultiPartRequest、 CosMultiPartRequest 、JakartaMultiPartRequest 。
• jakarta 支持多个文件使用同一个HTTP参数名。如果直接使用 WebWork 的 FileUpload 拦截器,推荐使用pell,因为当你上传中文文件名称的文件的时候,只有pell 包会正确的获得中文文件名称,apache common会将文件名称改为xxx.tmp这样的文件名,而cos会乱码, 因此我们唯一的选择只有 pell。
•cos 的功能比较强大,WebWork 的封装却使它丧失了很多的功能,cos 需要设置 request 的character encoding。WebWork的封装没有设置,所以就导致了cos的乱码问题,当然如果你单独 使用cos,则会避免此类问题。
3. 项目实战配置和使用
• 配置文件
action 配置:
<action name="uploadAttach" class=".....attach.action.uploadAttach" caption="上传附件"> <result name="success" type="dispatcher"> <param name="location">/result.jsp</param> </result> <result name="error" type="dispatcher"> <param name="location">/result.jsp</param> </result> <interceptor-ref name="defaultStack" /> <interceptor-ref name="fileUploadStack" /> //webwok 上传所需要的拦截栈 </action> //拦截栈的定义 <interceptor-stack name="fileUploadStack"> <interceptor-ref name="fileUpload"/> <interceptor-ref name="params"/> </interceptor-stack> //拦截栈对应的拦截器 <interceptor name="fileUpload" class="com.opensymphony.webwork.interceptor.FileUploadInterceptor"/> <interceptor name="params" class="com.opensymphony.xwork.interceptor.ParametersInterceptor"/>
•前端使用比较稳定、功能比较强大的 Ajaxupload这里就不多说了,有官方网址:jQuery AjaxUpload 上传图片代码
•通过对 Webwork 上传请求的封装和解析类的获取,所有的前戏都已经准备妥当,上传拦截器里面具体实现如下:
public String intercept(ActionInvocation invocation) throws Exception {if (!(ServletActionContext.getRequest() instanceof MultiPartRequestWrapper)) { if (log.isDebugEnabled()) { log.debug("bypass " + invocation.getProxy().getNamespace() + "/" + invocation.getProxy().getActionName()); } return invocation.invoke(); } Action action = invocation.getAction(); ValidationAware validation = null; if ((action instanceof ValidationAware)) { validation = (ValidationAware) action; } MultiPartRequestWrapper multiWrapper = (MultiPartRequestWrapper) ServletActionContext.getRequest(); if (multiWrapper.hasErrors()) { Collection errors = multiWrapper.getErrors(); Iterator i = errors.iterator(); while (i.hasNext()) { String error = (String) i.next(); if (validation != null) { validation.addActionError(error); } log.error(error); } } Enumeration e = multiWrapper.getFileParameterNames(); while ((e != null) && (e.hasMoreElements())) { String inputName = (String) e.nextElement(); String[] contentType = multiWrapper.getContentTypes(inputName); String[] fileName = multiWrapper.getFileNames(inputName); File[] file = multiWrapper.getFiles(inputName); if (file != null) { for (int i = 0; i < file.length; i++) { log.info("file " + inputName + " " + contentType[i] + " " + fileName[i] + " " + file[i]); } } if (file == null) { if (validation != null) { validation.addFieldError(inputName, "Could not upload file(s). Perhaps it is too large?"); } log.error("Error uploading: " + fileName); } else { invocation.getInvocationContext().getParameters().put(inputName, file); invocation.getInvocationContext().getParameters().put(inputName + "ContentType", contentType); invocation.getInvocationContext().getParameters().put(inputName + "FileName", fileName); } } String result = invocation.invoke(); for (Enumeration e1 = multiWrapper.getFileParameterNames(); e1 != null && e1.hasMoreElements();) { String inputValue = (String) e1.nextElement(); File file[] = multiWrapper.getFiles(inputValue); for (int i = 0; i < file.length; i++) { File f = file[i]; log.info("removing file " + inputValue + " " + f); if (f != null && f.isFile()) f.delete(); } } return result; }
•首先判断当前请求是否为 包含多媒体请求,如果是则记录日志,并执行 Action。
•然后判断在文件上传过程 MultiPartRequestWrapper 是否含有错误,将错误信息,返回给客户端,不在继续调用 Action。
•如果上面的判断条件都没有进行,开始遍历 MultiPartRequestWrapper 中的上传文件的参数,并将其中的文件名、文件内容类型放入Action 参数 map 中,供后面的业务类进行操作。
•在 WebWork 的 fileupload 拦截器功能中,它提供的 File只 是一个临时文件,Action 执行之后就会被自动删除,你必须在 Action中自己处理文件的存储问题,或者写到服务器的某个目录,或者保存到数据库中。如果你准备写到服务器的某个目录下面的话,你必须自己面临着处理文件同名的问题,但是实际上cos包已经提供了 文件重名的自动重命名规则。
通过以上代码给大家介绍了Webwork 实现文件上传下载的相关知识,希望对大家有所帮助。

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

Python提供以下选项打开下载文件:open()函数:使用指定路径和模式(如'r'、'w'、'a')打开文件。Requests库:使用其download()方法自动分配名称并直接打开文件。Pathlib库:使用write_bytes()和read_text()方法写入和读取文件内容。

如何利用Laravel实现文件上传和下载功能Laravel是一个流行的PHPWeb框架,提供了丰富的功能和工具,使得开发Web应用程序更加简单和高效。其中一个常用的功能就是文件上传和下载。本文将介绍如何利用Laravel实现文件上传和下载功能,并提供具体的代码示例。文件上传文件上传是指将本地的文件上传到服务器上保存。在Laravel中,我们可以使用文件上传

如何使用PHP函数进行邮件发送和接收的附件上传和下载?随着现代通信技术的迅猛发展,电子邮件已成为人们日常沟通和信息传递的重要途径。在Web开发中,经常会遇到需要发送和接收带有附件的邮件的需求。PHP作为一种强大的服务器端脚本语言,提供了丰富的函数和类库,可以简化邮件的处理过程。本文将介绍如何使用PHP函数进行邮件发送和接收的附件上传和下载。邮件发送首先,我们

实现Workerman文档中的文件上传与下载,需要具体代码示例引言:Workerman是一款高性能的PHP异步网络通讯框架,具备简洁、高效、易用等特点。在实际开发中,文件上传和下载是常见的功能需求,本文将介绍如何使用Workerman框架实现文件的上传和下载,并给出具体的代码示例。一、文件上传:文件上传是指将本地计算机上的文件传输至服务器端的操作。下面是使用

如何使用gRPC实现文件上传?创建配套服务定义,包括请求和响应消息。在客户端,打开要上传的文件并将其分成块,然后通过gRPC流流式传输发送到服务端。在服务端,接收文件块并将其存储到文件中。服务端在文件上传完成后发送响应,指示上传是否成功。

如何解决Java文件上传异常(FileUploadException)上传文件在Web开发中经常会遇到的一个问题是FileUploadException(文件上传异常)。它可能会由于各种原因而出现,例如文件大小超过限制、文件格式不匹配或者服务器配置不正确等。本文将介绍一些解决这些问题的方法,并提供相应的代码示例。限制上传文件的大小在大多数场景下,限制文件大小

如何使用Hyperf框架进行文件下载引言:在使用Hyperf框架开发Web应用程序时,文件下载是一个常见的需求。本文将介绍如何使用Hyperf框架进行文件下载,包括具体的代码示例。一、准备工作在开始之前,确保你已经安装好了Hyperf框架并成功创建了一个Hyperf应用程序。二、创建文件下载控制器首先,我们需要创建一个控制器来处理文件下载的请求。打开终端,进

PHP文件上传指南:如何使用move_uploaded_file函数处理上传文件在开发Web应用中,文件上传是一个常见的需求。PHP提供了一个方便的函数move_uploaded_file(),用于处理上传的文件。本文将向您介绍如何使用这个函数来实现文件上传功能。一、准备工作在开始之前,确保您的PHP环境已经配置好了文件上传的参数。您可以通过打开php.in
