Mr_*_*s_D 117 tomcat servlets file-upload servlet-3.0
我在这里读到,无论如何都不应该将文件保存在服务器中,因为它不是可移植的,事务性的并且需要外部参数.但是,鉴于我需要一个针对tomcat(7)的tmp解决方案,并且我对服务器机器有(相对)控制,我想知道:
保存文件的最佳位置是什么?我应该保存/WEB-INF/uploads(建议不要在这里)或某个地方$CATALINA_BASE(见这里)或......?JavaEE 6教程从用户获取路径(:wtf :).注意:该文件不应以任何方式下载.
我应该建立一个配置参数详见这里?我很欣赏一些代码(我宁愿给它一个相对路径 - 所以它至少是Tomcat可移植的) - Part.write()看起来很有希望 - 但显然需要一个绝对的路径
我对这种方法与数据库/ JCR存储库的缺点的阐述感兴趣
不幸的是 ,@ BalusC 的FileServlet专注于下载文件,而他在上传文件时的答案会跳过保存文件的位置.
容易转换为使用DB或JCR实现(如长耳兔)的解决方案将是优选的.
Bal*_*usC 160
将其存储在除 IDE的项目文件夹(即服务器的部署文件夹)之外的可访问位置中的任何位置,原因是上载图像的答案中提到的原因仅在刷新页面后可用:
IDE的项目文件夹中的更改不会立即反映在服务器的工作文件夹中.IDE中有一种后台作业,它注意服务器的工作文件夹与上次更新同步(这在IDE术语中称为"发布").这是您所看到的问题的主要原因.
在现实世界的代码中,存在将上传的文件存储在webapp的deploy文件夹中根本不起作用的情况.某些服务器(默认情况下或通过配置)不会将部署的WAR文件扩展到本地磁盘文件系统,而是完全在内存中.如果不基本编辑已部署的WAR文件并重新部署它,则无法在内存中创建新文件.
即使服务器将部署的WAR文件扩展到本地磁盘文件系统,所有新创建的文件也会在重新部署甚至简单重启时丢失,因为这些新文件不是原始WAR文件的一部分.
这真的不要紧,我或其他人那里正是本地磁盘文件系统将被保存,只要你做不曾经使用过getRealPath()的方法.在任何情况下使用该方法都令人担忧.
可以通过多种方式确定存储位置的路径.你必须全部由做自己.也许这就是你的混乱所致,因为你不知何故预计服务器会自动完成所有这一切.请注意,@MultipartConfig(location)并没有指定最后上传目的地,但对于案件的文件大小的临时存储位置超过存储器阈值.
因此,可以通过以下任一方式确定最终存储位置的路径:
硬编码:
File uploads = new File("/path/to/uploads");
Run Code Online (Sandbox Code Playgroud)环境变量来自SET UPLOAD_LOCATION=/path/to/uploads:
File uploads = new File(System.getenv("UPLOAD_LOCATION"));
Run Code Online (Sandbox Code Playgroud)服务器启动期间的VM参数-Dupload.location="/path/to/uploads":
File uploads = new File(System.getProperty("upload.location"));
Run Code Online (Sandbox Code Playgroud)*.properties文件条目为upload.location=/path/to/uploads:
File uploads = new File(properties.getProperty("upload.location"));
Run Code Online (Sandbox Code Playgroud)web.xml <context-param>名称upload.location和价值/path/to/uploads:
File uploads = new File(getServletContext().getInitParameter("upload.location"));
Run Code Online (Sandbox Code Playgroud)如果有,请使用服务器提供的位置,例如在JBoss AS/WildFly中:
File uploads = new File(System.getProperty("jboss.server.data.dir"), "uploads");
Run Code Online (Sandbox Code Playgroud)无论哪种方式,您都可以轻松地引用和保存文件,如下所示:
File file = new File(uploads, "somefilename.ext");
try (InputStream input = part.getInputStream()) {
Files.copy(input, file.toPath());
}
Run Code Online (Sandbox Code Playgroud)
或者,当您想要自动生成唯一文件名以防止用户覆盖具有相同名称的现有文件时:
File file = File.createTempFile("somefilename-", ".ext", uploads);
try (InputStream input = part.getInputStream()) {
Files.copy(input, file.toPath(), StandardCopyOption.REPLACE_EXISTING);
}
Run Code Online (Sandbox Code Playgroud)
如何part在JSP/Servlet中获取如何使用JSP/Servlet将文件上传到服务器?如何part在JSF中获取如何使用JSF 2.2 <h:inputFile>上传文件?保存的文件在哪里?
注意:千万不能使用Part#write(),因为它相对于定义的临时存储位置的路径解释@MultipartConfig(location).
我根据接受的答案发布了我的最终做法:
@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;
}
}
Run Code Online (Sandbox Code Playgroud)
其中:
@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);
}
}
Run Code Online (Sandbox Code Playgroud)
和/WEB-INF/app.properties:
upload.location=C:/_/
Run Code Online (Sandbox Code Playgroud)
HTH,如果你发现了一个错误,请告诉我
| 归档时间: |
|
| 查看次数: |
127139 次 |
| 最近记录: |