[tomcat] 將上傳的文件保存在servlet應用程序中的推薦方法


Answers

我根據公認的答案發布我的最終做法:

@SuppressWarnings("serial")
@WebServlet("/")
@MultipartConfig
public final class DataCollectionServlet extends Controller {

    private static final String UPLOAD_LOCATION_PROPERTY_KEY="upload.location";
    private String uploadsDirName;

    @Override
    public void init() throws ServletException {
        super.init();
        uploadsDirName = property(UPLOAD_LOCATION_PROPERTY_KEY);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        // ...
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        Collection<Part> parts = req.getParts();
        for (Part part : parts) {
            File save = new File(uploadsDirName, getFilename(part) + "_"
                + System.currentTimeMillis());
            final String absolutePath = save.getAbsolutePath();
            log.debug(absolutePath);
            part.write(absolutePath);
            sc.getRequestDispatcher(DATA_COLLECTION_JSP).forward(req, resp);
        }
    }

    // helpers
    private static String getFilename(Part part) {
        // courtesy of BalusC : http://stackoverflow.com/a/2424824/281545
        for (String cd : part.getHeader("content-disposition").split(";")) {
            if (cd.trim().startsWith("filename")) {
                String filename = cd.substring(cd.indexOf('=') + 1).trim()
                        .replace("\"", "");
                return filename.substring(filename.lastIndexOf('/') + 1)
                        .substring(filename.lastIndexOf('\\') + 1); // MSIE fix.
            }
        }
        return null;
    }
}

其中:

@SuppressWarnings("serial")
class Controller extends HttpServlet {

    static final String DATA_COLLECTION_JSP="/WEB-INF/jsp/data_collection.jsp";
    static ServletContext sc;
    Logger log;
    // private
    // "/WEB-INF/app.properties" also works...
    private static final String PROPERTIES_PATH = "WEB-INF/app.properties";
    private Properties properties;

    @Override
    public void init() throws ServletException {
        super.init();
        // synchronize !
        if (sc == null) sc = getServletContext();
        log = LoggerFactory.getLogger(this.getClass());
        try {
            loadProperties();
        } catch (IOException e) {
            throw new RuntimeException("Can't load properties file", e);
        }
    }

    private void loadProperties() throws IOException {
        try(InputStream is= sc.getResourceAsStream(PROPERTIES_PATH)) {
                if (is == null)
                    throw new RuntimeException("Can't locate properties file");
                properties = new Properties();
                properties.load(is);
        }
    }

    String property(final String key) {
        return properties.getProperty(key);
    }
}

和/WEB-INF/app.properties:

upload.location=C:/_/

HTH,如果你發現一個錯誤讓我知道

Question

我here讀到,不應該將文件保存在服務器中,因為它不是可移植的,事務性的並且需要外部參數。 然而,鑑於我需要一個tomcat(7)的tmp解決方案,並且我有(相對)我想知道的服務器機器的控制權:

  • 什麼是保存文件的最佳地點? 我應該將它保存在/WEB-INF/uploads (在here建議)還是在$CATALINA_BASE (見here )或...下的某個地方? JavaEE 6教程獲取用戶的路徑 (:wtf :)。 注意:文件不得以任何方式下載。

  • 我應該如何設置配置參數? 我會欣賞一些代碼(我寧願給它一個相對路徑 - 所以它至少是Tomcat的便攜式) - Part.write()看起來很有前途 - 但顯然需要一個絕對路徑

  • 我想對這種方法與數據庫/ JCR存儲庫的缺點進行闡述

不幸的是@BalusC的FileServlet專注於下載文件,而他關於上傳文件的answer跳過了保存文件的部分。

可以輕鬆轉換為使用DB或JCR實現(如jackrabbit )的解決方案將是更可取的。




Links