gpt4 book ai didi

java - 将 Flash 文件上传与 JSF 集成

转载 作者:搜寻专家 更新时间:2023-11-01 03:09:02 24 4
gpt4 key购买 nike

我看到我们可以通过flash文件上传来上传多个文件。喜欢SWFUploadYUI Uploader .是否可以将这些上传组件与 JSF 集成?

我想要的是一次选择多个文件。 Primefaces 文件 uploader 具有此功能,但在 IE7 中不起作用,因为 IE7 不支持 HTML5。

我需要创建一个包含各种字段的表单,例如下拉菜单、文本输入等,还需要添加一个文件 uploader 来选择多个文件。当单击 JSF 提交按钮时,表单将被验证,然后将继续。

我创建了一个用于上传多个文件的页面,但该页面对多个文件使用了多个输入文件组件。

任何引用都会对我很有帮助。我找到了另一个 SO thread那里发布的解决方案使用 JSP。我不明白如何使用它来满足我的要求。

更新

我创建了以下托管 bean:

import com.mhis.massupload.ucm.Service;

import java.util.List;
import java.util.UUID;
import java.util.logging.Logger;

import javax.faces.context.FacesContext;

import org.apache.commons.fileupload.FileItem;


public class UploadBean {
private Logger log = Logger.getLogger(getClass().getName());
private Service service;
private String key;

public UploadBean() {
super();
log.info("JYM");
init();
}

private void init() {
key = UUID.randomUUID().toString();
}

public String upload() {
System.out.println("Action Invoked.");
List<FileItem> fileFields = (List<FileItem>)FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get(key);
System.out.println(fileFields);

return "";
}

public void setKey(String key) {
this.key = key;
}

public String getKey() {
return key;
}
}

Servlet 是:

import java.io.IOException;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;


public class UploadServlet extends HttpServlet {

@SuppressWarnings("compatibility:-3560436533054762606")
private static final long serialVersionUID = 4122845079663279030L;

public void init(ServletConfig config) throws ServletException {
super.init(config);
}

public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("UploadServlet invoked.");
List<FileItem> fileFields = new ArrayList<FileItem>();

try {
List<FileItem> items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(request);
for (FileItem item : items) {
if (!item.isFormField()) {
fileFields.add(item);
System.out.println(item.getName());
}
}
} catch (Exception e) {
throw new ServletException(e);
}

String key = request.getParameter("key");
request.getSession().setAttribute(key, fileFields);
}
}

jspx页面:

<?xml version='1.0' encoding='utf-8'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<jsp:output omit-xml-declaration="true" doctype-root-element="HTML"
doctype-system="http://www.w3.org/TR/html4/loose.dtd"
doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"/>
<jsp:directive.page contentType="text/html;utf-8"/>
<f:view>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<script src="js/jquery-1.8.3.min.js" type="text/javascript"></script>
<script src="uploadify/jquery.uploadify.js" type="text/javascript"></script>
<link rel="stylesheet" media="screen" href="uploadify/uploadify.css"
type="text/css"/>
<script type="text/javascript">
$(document).ready(function() {
$('#uploadify').uploadify({
'swf': 'uploadify/uploadify.swf',
'uploader': '${pageContext.request.contextPath}/uploadServlet;jsessionid=${pageContext.session.id}?key=<h:outputText value="#{uploadBean.key}" />'
});
});

var upload = function() {
$('#uploadify').uploadify('upload','*');
}
</script>
<title>test</title>
</head>
<body>
<h:form enctype="multipart/form-data">
<input id="uploadify" type="file"/>
<h:commandLink action="#{uploadBean.upload}" value="Upload" />
</h:form>
</body>
</html>
</f:view>
</jsp:root>

我在这里使用 Uploadify。

我有两个问题:

  • List<FileItem> fileFieldsupload方法有时会返回 null ,有时会显示列表。我找不到原因。我试图获得 HttpSession来自 action方法 FacesContext.getCurrentInstance().getExternalContext().getSession(false)然后调用getAttribute()在它上面,那也总是在返回null .

  • 如果我设置 'auto': false,文件上传将在调用 upload(); 后启动方法并修改<h:commandLink/>如:<h:commandLink action="#{uploadBean.upload}" value="Upload" onclick="upload();"/>然后我得到异常,这是:

    org.apache.commons.fileupload.FileUploadBase$IOFileUploadException: Processing of multipart/form-data request failed. EOF after reading only: '2392369' of: '11626364' promised bytes, out of which at least: '0' were already buffered
    at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:367)
    at org.apache.commons.fileupload.servlet.ServletFileUpload.parseRequest(ServletFileUpload.java:126)
    at com.edfx.massupload.servlet.UploadServlet.doPost(UploadServlet.java:33)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
    at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)
    at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125)
    at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:300)
    at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:26)
    at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
    at oracle.security.jps.ee.http.JpsAbsFilter$1.run(JpsAbsFilter.java:119)
    at java.security.AccessController.doPrivileged(Native Method)
    at oracle.security.jps.util.JpsSubject.doAsPrivileged(JpsSubject.java:315)
    at oracle.security.jps.ee.util.JpsPlatformUtil.runJaasMode(JpsPlatformUtil.java:442)
    at oracle.security.jps.ee.http.JpsAbsFilter.runJaasMode(JpsAbsFilter.java:103)
    at oracle.security.jps.ee.http.JpsAbsFilter.doFilter(JpsAbsFilter.java:171)
    at oracle.security.jps.ee.http.JpsFilter.doFilter(JpsFilter.java:71)
    at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
    at oracle.dms.servlet.DMSServletFilter.doFilter(DMSServletFilter.java:139)
    at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
    at weblogic.servlet.internal.RequestEventsFilter.doFilter(RequestEventsFilter.java:27)
    at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
    at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.wrapRun(WebAppServletContext.java:3715)
    at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3681)
    at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
    at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:120)
    at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2277)
    at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2183)
    at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1454)
    at weblogic.work.ExecuteThread.execute(ExecuteThread.java:209)
    at weblogic.work.ExecuteThread.run(ExecuteThread.java:178)

在这种情况下也是 action方法在 servlet 执行之前执行。

我该如何解决这两个问题?

附言

我需要修改 uploadify.js 以设置 swf 文件的正确路径并更改取消按钮的 css。我已将 uploadify 的整个目录放在 Web-Content 中。

最佳答案

这是我做的解决方案,BalusC 对我的开发帮助很大。

平台和框架

  • 上传 v3.2
  • JSF 1.2
  • jQuery 1.8.3
  • 网络逻辑 10.3.5.0
  • Apache Commons 文件上传 1.2.2

多部分请求问题

JSF 1.2 无法处理多部分请求。所以如果<h:form/>包含 enctype="multipart/form-data"作为属性然后是 action命令组件的方法,如 <h:commandButton/>不会开火。解决方案是创建一个过滤器,它将与 Faces Servlet 一起工作。并显式处理多部分请求。这是过滤器:

package com.mhis.massupload.filter;

import java.io.IOException;

import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;


public class MultipartFilter implements Filter {
private FilterConfig filterConfig = null;

public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
}

public void destroy() {
filterConfig = null;
}

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if (!(request instanceof HttpServletRequest)) {
chain.doFilter(request, response);
return;
}

HttpServletRequest httpRequest = (HttpServletRequest)request;
boolean isMultipartContent = ServletFileUpload.isMultipartContent(httpRequest);

if (!isMultipartContent) {
chain.doFilter(request, response);
return;
}

try {
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setHeaderEncoding("UTF-8");
upload.setSizeMax(-1);

List<FileItem> items = upload.parseRequest(httpRequest);
final Map<String, String[]> parameterMap = new HashMap<String, String[]>();

for (FileItem item : items) {
if (item.isFormField()) {
processFormField(item, parameterMap);
}
}

chain.doFilter(new HttpServletRequestWrapper(httpRequest) {

public Map<String, String[]> getParameterMap() {
return parameterMap;
}

public String[] getParameterValues(String name) {
return (String[])parameterMap.get(name);
}

public String getParameter(String name) {
String[] params = getParameterValues(name);
if (params == null) {
return null;
}
return params[0];
}

public Enumeration<String> getParameterNames() {
return Collections.enumeration(parameterMap.keySet());
}
}, response);
} catch (Exception ex) {
ServletException servletException = new ServletException();
servletException.initCause(ex);
throw servletException;
}
}

private void processFormField(FileItem formField, Map<String, String[]> parameterMap) {
String name = formField.getFieldName();
String value = formField.getString();
String[] values = parameterMap.get(name);

if (values == null) {
parameterMap.put(name, new String[] { value });
} else {
int length = values.length;
String[] newValues = new String[length + 1];
System.arraycopy(values, 0, newValues, 0, length);
newValues[length] = value;
parameterMap.put(name, newValues);
}
}
}

这个过滤器在web.xml中的配置是:

<filter>
<filter-name>MultipartFilter</filter-name>
<filter-class>com.mhis.massupload.filter.MultipartFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>MultipartFilter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>

用于上传的 Javasctipt

$('#uploadify').uploadify({
'auto': false,
'buttonText' : 'Browse',
'fileSizeLimit': 0,
'swf': 'uploadify/uploadify.swf',
'uploader': '${pageContext.request.contextPath}/uploadservlet?key=<h:outputText value="#{uploadBean.key}" />',
'onQueueComplete' : function(queueData) {
$('.checkIn').click();
}
});

在我的要求中,我需要在单击表单的提交按钮时上传所有文件,而不是在文件添加到队列中时上传。这就是我设置 'auto': false 的原因. uploadify 文件夹已放入我的项目的 Web 内容中,因此该插件无法找到 uploadify.swf文件和取消按钮的图像。我必须修改 jquery.uploadify.js第 99 行,我已将其更改为 swf: 'uploadify/uploadify.swf'还有uploadify.css的第 74 行,我已将其更改为:

.uploadify-queue-item .cancel a {
background: url('../uploadify/uploadify-cancel.png') 0 0 no-repeat;
float: right;
height: 16px;
text-indent: -9999px;
width: 16px;
}

background被设置为 url('../img/uploadify-cancel.png') 0 0 no-repeat; , 但我没有 img 文件夹。

小服务程序

为了上传文件,我使用了 Servlet , 即 UplaodServlet ;这个 servlet 的配置是:

<servlet>
<servlet-name>UploadServlet</servlet-name>
<servlet-class>com.mhis.massupload.servlet.UploadServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UploadServlet</servlet-name>
<url-pattern>/uploadservlet</url-pattern>
</servlet-mapping>

uploadservlet已被用作uploader uploadify 的属性的配置。我还需要传递一个唯一键作为 Servlet 的请求参数. Servlet 的代码是:

package com.mhis.massupload.servlet;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;


public class UploadServlet extends HttpServlet {

@SuppressWarnings("compatibility:-6472602315203858426")
private static final long serialVersionUID = -3714619333861571457L;
private transient Logger log = Logger.getLogger(getClass().getName());

@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
}

@Override
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException {
boolean isMultipartContent = ServletFileUpload.isMultipartContent(request);

if (!isMultipartContent) {
return;
}

FileItem fileField = null;
try {
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setHeaderEncoding("UTF-8");
upload.setSizeMax(-1);

List<FileItem> items = upload.parseRequest(request);
final Map<String, String[]> parameterMap = new HashMap<String, String[]>();


for (FileItem item : items) {
if (!item.isFormField()) {
fileField = item;
}
}
} catch (Exception ex) {
log.severe(ex.getMessage());
}

if (fileField == null) {
return;
}

String key = request.getParameter("key");

List<FileItem> fileFields = (List<FileItem>)getServletContext().getAttribute(key);

if (fileFields == null) {
fileFields = new ArrayList<FileItem>();
getServletContext().setAttribute(key, fileFields);
}

fileFields.add(fileField);
}
}

我无法使用 Session放置有关上传文件的信息,所以我使用了ServletContext反而。有关更多信息,请参阅 here .

JSF 页面和上传按钮

因为我的需求是只有在验证后提交表单时才上传文件,所以我设置了'auto': false在 uploadify 的配置中。但这给我带来了麻烦,我已经在我原来的问题中发布了这个问题。为了解决这个问题,我声明了三个 input[type=button] .其中两个是普通的 HTML 按钮,最后一个是 <h:commandButton/> .我已经设置了这个 <h:commandButton/> 的可见性为 false 并使用了一个虚拟按钮来启动文件上传。上传完成后,我以编程方式生成了 click `` . Also I have shown a dummy button which don't have any click event associated with it; this the fail safe if, someone clicks on the Upload button twice during the upload is taking place then the the aforementioned click event fire will work unexpectedly. That why I am showing and hiding the buttons. Here is the completed .jspx` 页面:

<?xml version='1.0' encoding='utf-8'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<jsp:output omit-xml-declaration="true" doctype-root-element="HTML"
doctype-system="http://www.w3.org/TR/html4/loose.dtd"
doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"/>
<jsp:directive.page contentType="text/html;charset=utf-8"/>
<f:view>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<script src="js/jquery-1.8.3.min.js" type="text/javascript"></script>
<script src="uploadify/jquery.uploadify.js" type="text/javascript"></script>
<link rel="stylesheet" media="screen" href="uploadify/uploadify.css" type="text/css"/>

<script type="text/javascript">
$(function() {
$('#uploadify').uploadify({
'auto': false,
'buttonText' : 'Browse',
'fileSizeLimit': 0,
'swf': 'uploadify/uploadify.swf',
'uploader': '${pageContext.request.contextPath}/uploadservlet?key=<h:outputText value="#{uploadBean.key}" />',
'onQueueComplete' : function(queueData) {
$('.checkIn').click();
}
});

$('input[name=actualCheckIn]').on('click', function(event){
event.stopPropagation();
$(this).hide();
$('input[name=fakeCheckIn]').show();
$('#uploadify').uploadify('upload','*');
return false;
});
});

var upload = function() {
}
</script>

<title>Upload</title>
</head>
<body>
<h:form enctype="multipart/form-data">
<input id="uploadify" type="file"/>
<h:commandButton value="Check In" action="#{uploadBean.upload}" styleClass="checkIn" style="display: none"/>
<input type="button" value="Check In" name="actualCheckIn"/>
<input type="button" value="Check In" onclick="return false;" name="fakeCheckIn" style="display: none"/>
</h:form>
</body>
</html>
</f:view>
</jsp:root>

通过这种方式,当 uplaodify 完成时,它被上传到 servlet,acution JSF 被触发。

托管 Bean

托管 bean 的作用域为 Session这是它的代码:

package com.mhis.massupload.bean;


import com.mhis.massupload.dto.DocInfo;

import java.io.Serializable;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.faces.context.FacesContext;

import javax.servlet.ServletContext;

import oracle.stellent.ridc.IdcClientException;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.lang3.StringUtils;


public class UploadBean implements Serializable {
@SuppressWarnings("compatibility:-930710930183135088")
private static final long serialVersionUID = -491462816764274947L;
private transient Logger log = Logger.getLogger(getClass().getName());

private String key;
private transient Service service;

public UploadBean() throws IdcClientException {
init();
}

private void init() throws IdcClientException {
key = UUID.randomUUID().toString();
}

public String upload() {
List<FileItem> fileFields = (List<FileItem>) FacesContext.getCurrentInstance().getExternalContext().getApplicationMap().remove(key);
List<DocInfo> docInfos = new ArrayList<DocInfo>();

if (fileFields != null) {
for (FileItem fileField : fileFields) {
if(StringUtils.isNotBlank(fileField.getName())) {
try {
System.out.println("Check in: " + fileField.getName());
} catch (Exception e) {
log.log(Level.SEVERE, e.getMessage());
}
}
}
}

FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("docInfos", docInfos);

return "report";
}

public void setKey(String key) {
this.key = key;
}

public String getKey() {
return key;
}
}

这很有效。

希望对您有所帮助。

关于java - 将 Flash 文件上传与 JSF 集成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14260583/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com