0

我在 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 行)

不管我在客户端选择多少文件,文件列表总是空的。

非常感谢您在这方面的帮助 - 非常感谢

4

1 回答 1

0

我知道这很老了,但我遇到了同样的问题。在我的实现中,我尝试将示例端点代码改编为我的 Spring MVC 项目。我发现 Spring MVC 框架实际上在将请求传递给我的控制器并检测多部分、获取参数等之前调用了相同的 Apache ServletFileUpload.parseRequest。无论我是否使用 MutlipartHttpServlet 请求,框架都在解析多部分请求,或者只需将 HttpServletRequest 作为我对控制器方法的签名。当我在 MultipartUploadParser 中的代码再次点击 ServletFileUpload.parseRequest 时,这一次它返回了一个空列表,因为它们已经被解析了。

Fine Uploader 的 git repo 中的端点示例代码按原样工作,只是我对 Spring MVC 的适应没有工作。

于 2017-05-17T00:28:28.187 回答