나는 여기 에서 파일이 이식 가능하지 않고 트랜잭션적이고 외부 매개 변수가 필요하기 때문에 어쨌든 서버에 파일을 저장해서는 안된다는 것을 읽었습니다 . 그러나 tomcat (7)에 대한 tmp 솔루션이 필요하고 알고 싶은 서버 시스템에 대한 (상대적) 제어권이 있다는 점을 감안할 때 :
-
파일을 저장하기에 가장 좋은 장소는 어디입니까?
/WEB-INF/uploads
( 여기 에 대해 권고 됨 ) 또는 아래$CATALINA_BASE
( 여기 참조 ) 또는 …에 저장해야합니까 ? JavaEE 6 자습서 는 사용자 (: wtf 🙂 로부터 경로를 가져옵니다 . 주의 : 파일을 어떤 방법으로도 다운로드 할 수 없어야합니다. -
여기에 설명 된대로 구성 매개 변수를 설정해야합니까 ? 나는 일부 코드를 고맙게 생각합니다 (상대 경로를 제공하고 싶습니다-적어도 Tomcat 이식 가능)-
Part.write()
유망 해 보이지만 분명히 절대 경로가 필요합니다. -
이 접근법의 단점과 데이터베이스 / JCR 저장소의 단점에 대한 설명에 관심이 있습니다.
불행히도 @BalusC 의 FileServlet 은 파일 다운로드에 집중하고 파일 업로드에 대한 그의 대답 은 파일 저장 위치에 대한 부분을 건너 뜁니다.
DB 또는 JCR 구현 (예 : jackrabbit ) 을 사용하도록 쉽게 변환 할 수있는 솔루션 이 바람직합니다.
답변
페이지를 새로 고친 후에 만 사용할 수있는 업로드 된 이미지 에 대한 답변에 언급 된 이유로 IDE의 프로젝트 폴더 (일명 서버의 배포 폴더)를 제외하고 액세스 가능한 위치에 저장합니다 .
IDE 프로젝트 폴더의 변경 사항은 서버의 작업 폴더에 즉시 반영되지 않습니다. IDE에는 서버의 작업 폴더가 마지막 업데이트와 동기화되도록하는 일종의 백그라운드 작업이 있습니다 ( “게시”라고하는 IDE 용어). 이것이 당신이보고있는 문제의 주요 원인입니다.
실제 코드에서는 업로드 된 파일을 webapp의 배포 폴더에 저장하는 것이 전혀 작동하지 않는 상황이 있습니다. 일부 서버는 기본적으로 또는 구성에 따라 배포 된 WAR 파일을 로컬 디스크 파일 시스템으로 확장하지 않고 대신 메모리에서 완전히 확장합니다. 기본적으로 배포 된 WAR 파일을 편집하고 다시 배포하지 않고는 메모리에 새 파일을 만들 수 없습니다.
서버가 배포 된 WAR 파일을 로컬 디스크 파일 시스템으로 확장하더라도 새 파일이 원래 WAR 파일의 일부가 아니기 때문에 새로 생성 된 모든 파일은 재배포 또는 간단한 재시작시 손실됩니다.
method를 사용 하지 않는 한getRealPath()
나 또는 다른 사람에게 정확히 로컬 디스크 파일 시스템에 저장되는 것은 중요 하지 않습니다 . 그 방법을 사용하는 것은 어쨌든 놀라운 일입니다.
저장 위치에 대한 경로는 여러 방법으로 정의 될 수 있습니다. 모든 것을 혼자서 해야합니다 . 아마도 이것은 서버가 모든 것을 자동으로 수행 할 것으로 예상했기 때문에 혼란이 발생하는 곳일 것입니다. 주의하시기 바랍니다 @MultipartConfig(location)
않습니다 하지 최종 업로드 대상을 지정하지만, 사건 파일 크기에 대한 임시 저장 위치는 메모리 저장 임계 값을 초과합니다.
따라서 최종 저장 위치에 대한 경로는 다음 방법 중 하나로 정의 할 수 있습니다.
-
하드 코딩 됨 :
File uploads = new File("/path/to/uploads");
-
다음을 통한 환경 변수
SET UPLOAD_LOCATION=/path/to/uploads
:File uploads = new File(System.getenv("UPLOAD_LOCATION"));
-
다음을 통해 서버 시작 중 VM 인수
-Dupload.location="/path/to/uploads"
:File uploads = new File(System.getProperty("upload.location"));
-
*.properties
파일 항목upload.location=/path/to/uploads
:File uploads = new File(properties.getProperty("upload.location"));
-
web.xml
<context-param>
이름upload.location
과 가치/path/to/uploads
:File uploads = new File(getServletContext().getInitParameter("upload.location"));
-
있는 경우 서버 제공 위치를 사용합니다 (예 : JBoss AS / WildFly) .
File uploads = new File(System.getProperty("jboss.server.data.dir"), "uploads");
어느 쪽이든 다음과 같이 파일을 쉽게 참조하고 저장할 수 있습니다.
File file = new File(uploads, "somefilename.ext");
try (InputStream input = part.getInputStream()) {
Files.copy(input, file.toPath());
}
또는 사용자가 우연히 동일한 이름으로 기존 파일을 덮어 쓰지 못하도록 고유 한 파일 이름을 자동 생성하려는 경우 :
File file = File.createTempFile("somefilename-", ".ext", uploads);
try (InputStream input = part.getInputStream()) {
Files.copy(input, file.toPath(), StandardCopyOption.REPLACE_EXISTING);
}
part
JSP / Servlet에서 얻는 방법 은 JSP / Servlet 을 사용하여 서버에 파일을 업로드하는 방법에 나와 있습니다. part
JSF 에서 얻는 방법 은 어떻게 JSF 2.2 <h : inputFile>을 사용하여 파일을 업로드합니까? 저장된 파일은 어디에 있습니까?
참고 :에 정의 된 임시 저장 위치에 상대적인 경로를 해석하므로 사용 하지 마십시오 .Part#write()
@MultipartConfig(location)
또한보십시오:
- JSF에 업로드 된 파일을 저장하는 방법 (JSF 대상이지만 원칙은 거의 동일)
- Java 웹 애플리케이션의 애플리케이션 서버 외부에서 정적 데이터를 제공하는 가장 간단한 방법 (다시 제공하려는 경우)
- 생성 된 파일을 서블릿 기반 웹 애플리케이션에 임시로 저장하는 방법
답변
받아 들인 답변을 기반으로 최종 방법을 게시합니다.
@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 및 버그를 찾으면 알려주십시오.