我在 struts 系统中使用 Fineuploader,但在获取服务器代码中的文件列表时遇到问题。
我的jsp包含以下代码:
$("#fine-uploader").fineUploader({
debug: true,
request: {
endpoint: '/NRGI/act_MultiPhotoUpload.do'
},
deleteFile: {
enabled: true,
endpoint: '/uploads'
},
retry: {
enableAuto: true
}
});
在页面底部附近有以下 div:
<div id="fine-uploader"></div>
动作 actMultiPhotoUpload 通过 struts.config.xml 文件指向一个类:
<action path="/act_MultiPhotoUpload" name="FileUploadForm" scope="request" validate="true"
type="com.solarcentury.nrgi.document.action.MultiUploadAction"
input="/D5_PhotoLibrary.jsp">
</action>
MultiUploadAction 类取自您的 UploadReceiver,如下所示:
public class MultiUploadAction extends Action {
static Static_Env_Object seo = new Static_Env_Object();
private String UPLOAD_NOT_ALLOWED = "exe";
private EnvUtils eu;
// JUST FOR TESTING
private static final File UPLOAD_DIR = new File("Test/uploads");
private static File TEMP_DIR = new File("Test/uploadsTemp");
private static String CONTENT_LENGTH = "Content-Length";
private static int SUCCESS_RESPONSE_CODE = 200;
@Override
public ActionForward perform(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
HttpSession session = request.getSession();
String sId = session.getId();
eu = new EnvUtils(seo.get_Env_Name(), this.getClass().getSimpleName());
/* **************************************** */
/* * The code for the session timeout check */
/* **************************************** */
if (session.getAttribute("SESS_User") == null) {
eu.log("NO SESSION", "Session timed out...");
return (mapping.findForward("globaltimeout"));
}
UserObject suo = new UserObj_Util(session).get_SessUser();
WebAlertMessages wam = new WebAlertMessages(request, suo.get_Language_ID());
DemonUtil du = new DemonUtil(seo.get_Env_Name());
// DateUtils dateUtil = new DateUtils();
RequestParser requestParser = null;
boolean isIframe = request.getHeader("X-Requested-With") == null || !request.getHeader("X-Requested-With").equals("XMLHttpRequest");
try
{
// resp.setContentType(isIframe ? "text/html" : "text/plain");
response.setContentType("text/plain");
response.setStatus(SUCCESS_RESPONSE_CODE);
// resp.addHeader("Access-Control-Allow-Origin", "http://192.168.130.118:8080");
// resp.addHeader("Access-Control-Allow-Credentials", "true");
// resp.addHeader("Access-Control-Allow-Origin", "*");
if (ServletFileUpload.isMultipartContent(request))
{
MultipartUploadParser multipartUploadParser = new MultipartUploadParser(request, TEMP_DIR, request.getSession().getServletContext());
requestParser = RequestParser.getInstance(request, multipartUploadParser);
writeFileForMultipartRequest(requestParser);
writeResponse(response.getWriter(), requestParser.generateError() ? "Generated error" : null, isIframe, false, requestParser);
}
else
{
requestParser = RequestParser.getInstance(request, null);
//handle POST delete file request
if (requestParser.getMethod() != null
&& requestParser.getMethod().equalsIgnoreCase("DELETE"))
{
String uuid = requestParser.getUuid();
handleDeleteFileRequest(uuid, response);
}
else
{
writeFileForNonMultipartRequest(request, requestParser);
writeResponse(response.getWriter(), requestParser.generateError() ? "Generated error" : null, isIframe, false, requestParser);
}
}
} catch (Exception e)
{
eu.log("UploadReceiver","Problem handling upload request" + e);
if (e instanceof MultiUploadAction.MergePartsException)
{
writeResponse(response.getWriter(), e.getMessage(), isIframe, true, requestParser);
}
else
{
writeResponse(response.getWriter(), e.getMessage(), isIframe, false, requestParser);
}
}
return (new ActionForward(mapping.getInput()));
}
我使用网站上服务器 java 示例中的 MultipartUploadParser、RequestParser。
当我单步执行代码时,无论我选择上传多少个文件,文件列表总是空的。显然我在这里做了一些愚蠢的事情,但请提供任何指导。
我看到了一个类似的支持问题,其中提问者在获取文件列表时遇到了问题,也使用了 struts,但没有针对该问题的答案
添加于 2013 年 11 月 14 日
完整代码如下:
MultiUploadAction.java 的完整列表如下:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.solarcentury.nrgi.document.action;
/**
*
* @author Roy
*/
import DemonWeb.DmForms.FileUploadForm;
import DemonWeb.DmLogic.DemonUtil;
import DemonWeb.DmLogic.Project;
import DemonWeb.DmSession.Static_Env_Object;
import DemonWeb.DmSession.UserObj_Util;
import DemonWeb.DmSession.UserObject;
import DemonWeb.DmSession.WebAlertMessages;
import DemonWeb.Utils.EnvUtils;
import com.solarcentury.nrgi.document.bean.Document;
import com.solarcentury.nrgi.document.logic.DocumentController;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
import java.util.Enumeration;
import java.util.Collections;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.upload.FormFile;
/**
*
* @author ajantham
*/
public class MultiUploadAction extends Action {
static Static_Env_Object seo = new Static_Env_Object();
private String UPLOAD_NOT_ALLOWED = "exe";
private EnvUtils eu;
// JUST FOR TESTING
private static final File UPLOAD_DIR = new File("uploads");
private static File TEMP_DIR = new File("uploadsTemp");
private static String CONTENT_LENGTH = "Content-Length";
private static int SUCCESS_RESPONSE_CODE = 200;
@Override
public ActionForward perform(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
HttpSession session = request.getSession();
String sId = session.getId();
eu = new EnvUtils(seo.get_Env_Name(), this.getClass().getSimpleName());
/* **************************************** */
/* * The code for the session timeout check */
/* **************************************** */
if (session.getAttribute("SESS_User") == null) {
eu.log("NO SESSION", "Session timed out...");
return (mapping.findForward("globaltimeout"));
}
UserObject suo = new UserObj_Util(session).get_SessUser();
WebAlertMessages wam = new WebAlertMessages(request, suo.get_Language_ID());
DemonUtil du = new DemonUtil(seo.get_Env_Name());
// DateUtils dateUtil = new DateUtils();
RequestParser requestParser = null;
boolean isIframe = request.getHeader("X-Requested-With") == null || !request.getHeader("X-Requested-With").equals("XMLHttpRequest");
try
{
// resp.setContentType(isIframe ? "text/html" : "text/plain");
response.setContentType("text/plain");
response.setStatus(SUCCESS_RESPONSE_CODE);
// resp.addHeader("Access-Control-Allow-Origin", "http://192.168.130.118:8080");
// resp.addHeader("Access-Control-Allow-Credentials", "true");
// resp.addHeader("Access-Control-Allow-Origin", "*");
if (ServletFileUpload.isMultipartContent(request))
{
MultipartUploadParser multipartUploadParser = new MultipartUploadParser(request, TEMP_DIR, request.getSession().getServletContext());
requestParser = RequestParser.getInstance(request, multipartUploadParser);
writeFileForMultipartRequest(requestParser);
writeResponse(response.getWriter(), requestParser.generateError() ? "Generated error" : null, isIframe, false, requestParser);
}
else
{
requestParser = RequestParser.getInstance(request, null);
//handle POST delete file request
if (requestParser.getMethod() != null
&& requestParser.getMethod().equalsIgnoreCase("DELETE"))
{
String uuid = requestParser.getUuid();
handleDeleteFileRequest(uuid, response);
}
else
{
writeFileForNonMultipartRequest(request, requestParser);
writeResponse(response.getWriter(), requestParser.generateError() ? "Generated error" : null, isIframe, false, requestParser);
}
}
} catch (Exception e)
{
eu.log("UploadReceiver","Problem handling upload request" + e);
if (e instanceof MultiUploadAction.MergePartsException)
{
writeResponse(response.getWriter(), e.getMessage(), isIframe, true, requestParser);
}
else
{
writeResponse(response.getWriter(), e.getMessage(), isIframe, false, requestParser);
}
}
return (new ActionForward(mapping.getInput()));
}
public void doDelete(HttpServletRequest req, HttpServletResponse resp) throws IOException
{
String uuid = req.getPathInfo().replaceAll("/", "");
handleDeleteFileRequest(uuid, resp);
}
private void handleDeleteFileRequest(String uuid, HttpServletResponse resp) throws IOException
{
FileUtils.deleteDirectory(new File(UPLOAD_DIR, uuid));
if (new File(UPLOAD_DIR, uuid).exists())
{
eu.log("UploadReceiver","couldn't find or delete " + uuid);
}
else
{
eu.log("UploadReceiver","deleted " + uuid);
}
resp.setStatus(SUCCESS_RESPONSE_CODE);
// resp.addHeader("Access-Control-Allow-Origin", "*");
}
private void writeFileForNonMultipartRequest(HttpServletRequest req, RequestParser requestParser) throws Exception
{
File dir = new File(UPLOAD_DIR, requestParser.getUuid());
dir.mkdirs();
String contentLengthHeader = req.getHeader(CONTENT_LENGTH);
long expectedFileSize = Long.parseLong(contentLengthHeader);
if (requestParser.getPartIndex() >= 0)
{
writeFile(req.getInputStream(), new File(dir, requestParser.getUuid() + "_" + String.format("%05d", requestParser.getPartIndex())), null);
if (requestParser.getTotalParts()-1 == requestParser.getPartIndex())
{
File[] parts = getPartitionFiles(dir, requestParser.getUuid());
File outputFile = new File(dir, requestParser.getFilename());
for (File part : parts)
{
mergeFiles(outputFile, part);
}
assertCombinedFileIsVaid(requestParser.getTotalFileSize(), outputFile, requestParser.getUuid());
deletePartitionFiles(dir, requestParser.getUuid());
}
}
else
{
writeFile(req.getInputStream(), new File(dir, requestParser.getFilename()), expectedFileSize);
}
}
private void writeFileForMultipartRequest(RequestParser requestParser) throws Exception
{
File dir = new File(UPLOAD_DIR, requestParser.getUuid());
dir.mkdirs();
if (requestParser.getPartIndex() >= 0)
{
writeFile(requestParser.getUploadItem().getInputStream(), new File(dir, requestParser.getUuid() + "_" + String.format("%05d", requestParser.getPartIndex())), null);
if (requestParser.getTotalParts()-1 == requestParser.getPartIndex())
{
File[] parts = getPartitionFiles(dir, requestParser.getUuid());
File outputFile = new File(dir, requestParser.getOriginalFilename());
for (File part : parts)
{
mergeFiles(outputFile, part);
}
assertCombinedFileIsVaid(requestParser.getTotalFileSize(), outputFile, requestParser.getUuid());
deletePartitionFiles(dir, requestParser.getUuid());
}
}
else
{
writeFile(requestParser.getUploadItem().getInputStream(), new File(dir, requestParser.getFilename()), null);
}
}
private void assertCombinedFileIsVaid(int totalFileSize, File outputFile, String uuid) throws MultiUploadAction.MergePartsException
{
if (totalFileSize != outputFile.length())
{
deletePartitionFiles(UPLOAD_DIR, uuid);
outputFile.delete();
throw new MultiUploadAction.MergePartsException("Incorrect combined file size!");
}
}
private static class PartitionFilesFilter implements FilenameFilter
{
private String filename;
PartitionFilesFilter(String filename)
{
this.filename = filename;
}
@Override
public boolean accept(File file, String s)
{
return s.matches(Pattern.quote(filename) + "_\\d+");
}
}
private static File[] getPartitionFiles(File directory, String filename)
{
File[] files = directory.listFiles(new MultiUploadAction.PartitionFilesFilter(filename));
Arrays.sort(files);
return files;
}
private static void deletePartitionFiles(File directory, String filename)
{
File[] partFiles = getPartitionFiles(directory, filename);
for (File partFile : partFiles)
{
partFile.delete();
}
}
private File mergeFiles(File outputFile, File partFile) throws IOException
{
FileOutputStream fos = new FileOutputStream(outputFile, true);
try
{
FileInputStream fis = new FileInputStream(partFile);
try
{
IOUtils.copy(fis, fos);
}
finally
{
IOUtils.closeQuietly(fis);
}
}
finally
{
IOUtils.closeQuietly(fos);
}
return outputFile;
}
private File writeFile(InputStream in, File out, Long expectedFileSize) throws IOException
{
FileOutputStream fos = null;
try
{
fos = new FileOutputStream(out);
IOUtils.copy(in, fos);
if (expectedFileSize != null)
{
Long bytesWrittenToDisk = out.length();
if (!expectedFileSize.equals(bytesWrittenToDisk))
{
eu.log("UploadReceiver","Expected file {} to be {} bytes; file on disk is {} bytes " + new Object[] { out.getAbsolutePath(), expectedFileSize, 1 });
out.delete();
throw new IOException(String.format("Unexpected file size mismatch. Actual bytes %s. Expected bytes %s.", bytesWrittenToDisk, expectedFileSize));
}
}
return out;
}
catch (Exception e)
{
throw new IOException(e);
}
finally
{
IOUtils.closeQuietly(fos);
}
}
private void writeResponse(PrintWriter writer, String failureReason, boolean isIframe, boolean restartChunking, RequestParser requestParser)
{
if (failureReason == null)
{
// if (isIframe)
// {
// writer.print("{\"success\": true, \"uuid\": \"" + requestParser.getUuid() + "\"}<script src=\"http://192.168.130.118:8080/client/js/iframe.xss.response.js\"></script>");
// }
// else
// {
writer.print("{\"success\": true}");
// }
}
else
{
if (restartChunking)
{
writer.print("{\"error\": \"" + failureReason + "\", \"reset\": true}");
}
else
{
// if (isIframe)
// {
// writer.print("{\"error\": \"" + failureReason + "\", \"uuid\": \"" + requestParser.getUuid() + "\"}<script src=\"http://192.168.130.118:8080/client/js/iframe.xss.response.js\"></script>");
// }
// else
// {
writer.print("{\"error\": \"" + failureReason + "\"}");
// }
}
}
}
private class MergePartsException extends Exception
{
MergePartsException(String message)
{
super(message);
}
}
}
MultipartUploadParser.java 的完整源码如下:
package com.solarcentury.nrgi.document.action;
import DemonWeb.DmSession.Static_Env_Object;
import DemonWeb.Utils.EnvUtils;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.FileCleanerCleanup;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileCleaningTracker;
import org.apache.commons.lang3.StringUtils;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.*;
public class MultipartUploadParser
{
// final Logger log = LoggerFactory.getLogger(MultipartUploadParser.class);
static Static_Env_Object seo = new Static_Env_Object();
private EnvUtils eu;
private Map<String, String> params = new HashMap<String, String>();
private List<FileItem> files = new ArrayList<FileItem>();
// fileItemsFactory is a field (even though it's scoped to the constructor) to prevent the
// org.apache.commons.fileupload.servlet.FileCleanerCleanup thread from attempting to delete the
// temp file before while it is still being used.
//
// FileCleanerCleanup uses a java.lang.ref.ReferenceQueue to delete the temp file when the FileItemsFactory marker object is GCed
private DiskFileItemFactory fileItemsFactory;
public MultipartUploadParser(HttpServletRequest request, File repository, ServletContext context) throws Exception
{
this.eu = new EnvUtils(seo.get_Env_Name(), "MultipartUploadParser " + "1.0.0.0");
if (!repository.exists() && !repository.mkdirs())
{
throw new IOException("Unable to mkdirs to " + repository.getAbsolutePath());
}
fileItemsFactory = setupFileItemFactory(repository, context);
ServletFileUpload upload = new ServletFileUpload(fileItemsFactory);
List<FileItem> formFileItems = upload.parseRequest(request);
parseFormFields(formFileItems);
if (files.isEmpty())
{
eu.log("MultipartUploadParser","No files were found when processing the request. Debugging info follows");
writeDebugInfo(request);
throw new FileUploadException("No files were found when processing the request.");
}
else
{
writeDebugInfo(request);
}
}
private DiskFileItemFactory setupFileItemFactory(File repository, ServletContext context)
{
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setSizeThreshold(DiskFileItemFactory.DEFAULT_SIZE_THRESHOLD);
factory.setRepository(repository);
FileCleaningTracker pTracker = FileCleanerCleanup.getFileCleaningTracker(context);
factory.setFileCleaningTracker(pTracker);
return factory;
}
private void writeDebugInfo(HttpServletRequest request)
{
eu.log("MultipartUploadParser","-- POST HEADERS --");
for (String header : Collections.list((Enumeration<String>) request.getHeaderNames()))
{
eu.log("MultipartUploadParser", header + "header " + request.getHeader(header));
}
eu.log("MultipartUploadParser","-- POST PARAMS --");
for (String key : params.keySet())
{
eu.log("MultipartUploadParser", key + " key " + params.get(key));
}
}
private void parseFormFields(List<FileItem> items) throws UnsupportedEncodingException
{
for (FileItem item : items)
{
if (item.isFormField())
{
String key = item.getFieldName();
String value = item.getString("UTF-8");
if (StringUtils.isNotBlank(key))
{
params.put(key, StringUtils.defaultString(value));
}
}
else
{
files.add(item);
}
}
}
public Map<String, String> getParams()
{
return params;
}
public List<FileItem> getFiles()
{
if (files.isEmpty())
{
throw new RuntimeException("No FileItems exist.");
}
return files;
}
public FileItem getFirstFile()
{
if (files.isEmpty())
{
throw new RuntimeException("No FileItems exist.");
}
return files.iterator().next();
}
}
MultiUploadAction 决定请求是MultipartContent,因此调用MultipartUploadParser。这个类成功地检查了目录结构,然后使用它的方法 ParseFormFields 来构建一个文件列表。但是它没有找到任何文件或表单字段,等等 MultipartUploadParser files.isEmpty() 的第 62 行为真,因此抛出异常(第 70 行)
不管我在客户端选择多少文件,文件列表总是空的。
非常感谢您在这方面的帮助 - 非常感谢