PrimeFaces p : fileUpload를 사용하는 방법? 리스너 메소드가 호출되지 않거나 UploadedFile이 널 (null) / 오류 발생 / 사용 불가능
PrimeFaces를 사용하여 파일을 업로드하려고하는데 fileUploadListener
업로드가 완료된 후 메서드가 호출되지 않습니다.
보기는 다음과 같습니다.
<h:form>
<p:fileUpload fileUploadListener="#{fileUploadController.handleFileUpload}"
mode="advanced"
update="messages"
sizeLimit="100000"
allowTypes="/(\.|\/)(gif|jpe?g|png)$/"/>
<p:growl id="messages" showDetail="true"/>
</h:form>
그리고 콩 :
@ManagedBean
@RequestScoped
public class FileUploadController {
public void handleFileUpload(FileUploadEvent event) {
FacesMessage msg = new FacesMessage("Succesful", event.getFile().getFileName() + " is uploaded.");
FacesContext.getCurrentInstance().addMessage(null, msg);
}
}
메서드에 중단 점을 두었지만 호출되지 않았습니다. mode="simple"
및을 사용할 때 ajax="false"
호출되었지만 고급 모드에서 작동하기를 원합니다. Netbeans 및 Glassfish 3.1을 사용하고 있습니다.
구성 및 문제 해결 방법 <p:fileUpload>
은 PrimeFaces 버전에 따라 다릅니다.
모든 PrimeFaces 버전
아래 요구 사항은 모든 PrimeFaces 버전에 적용됩니다.
의
enctype
속성<h:form>
을로 설정해야multipart/form-data
합니다. 이것이 없으면 ajax 업로드가 작동 할 수 있지만 일반적인 브라우저 동작은 지정되지 않으며 양식 구성 및 웹 브라우저 만들기 / 버전에 따라 다릅니다. 항상 안전한쪽에 있도록 지정하십시오.사용할 때
mode="advanced"
(즉, ajax 업로드, 이것이 기본값),<h:head>
(마스터) 템플릿에 있는지 확인하십시오 . 이렇게하면 필요한 JavaScript 파일이 제대로 포함됩니다. 이것은mode="simple"
(AJAX가 아닌 업로드)에는 필요하지 않지만 다른 모든 PrimeFaces 구성 요소의 모양과 기능이 깨질 수 있으므로 어쨌든 놓치고 싶지 않습니다.사용하는 경우
mode="simple"
(즉, 비 아약스 업로드를) 다음 어떤 PrimeFaces가에 의해 버튼 / 링크를 명령에 아약스를 사용할 수 있어야합니다ajax="false"
, 당신은 사용해야합니다<p:fileUpload value>
으로<p:commandButton action>
대신<p:fileUpload fileUploadListener>
.
따라서 ajax 지원으로 (자동) 파일 업로드를 원한다면 ( <h:head>
!) :
<h:form enctype="multipart/form-data">
<p:fileUpload fileUploadListener="#{bean.upload}" auto="true" />
</h:form>
public void upload(FileUploadEvent event) {
UploadedFile uploadedFile = event.getFile();
String fileName = uploadedFile.getFileName();
String contentType = uploadedFile.getContentType();
byte[] contents = uploadedFile.getContents(); // Or getInputStream()
// ... Save it, now!
}
또는 ajax가 아닌 파일 업로드를 원하는 경우 :
<h:form enctype="multipart/form-data">
<p:fileUpload mode="simple" value="#{bean.uploadedFile}" />
<p:commandButton value="Upload" action="#{bean.upload}" ajax="false" />
</h:form>
private UploadedFile uploadedFile; // +getter+setter
public void upload() {
String fileName = uploadedFile.getFileName();
String contentType = uploadedFile.getContentType();
byte[] contents = uploadedFile.getContents(); // Or getInputStream()
// ... Save it, now!
}
같은 아약스 관련 속성이 있습니다하십니까 auto
, allowTypes
, update
, onstart
, oncomplete
, 등이있다 무시 에를 mode="simple"
. 따라서 이러한 경우 지정할 필요가 없습니다.
또한 나중에 HTTP 요청에 의해 호출 된 다른 Bean 메소드가 아니라 위에 언급 된 메소드 내에서 즉시 파일 내용을 읽어야합니다 . 이는 업로드 된 파일 내용이 요청 범위이므로 이후 / 다른 HTTP 요청에서 사용할 수 없기 때문입니다. 이후 요청에서이를 읽으려는 시도는 대부분 java.io.FileNotFoundException
임시 파일에서 끝날 것입니다 .
PrimeFaces 5.x
JSF 2.2를 사용하고 있으며 faces-config.xml
JSF 2.2 버전을 준수하는 것으로 선언 된 경우 추가 구성이 필요하지 않습니다 . PrimeFaces 파일 업로드 필터는 전혀 필요하지 않습니다. 사용하는 대상 서버에 따라 JSF를 올바르게 설치하고 구성하는 방법이 명확하지 않은 경우 Maven을 통해 JSF 라이브러리를 올바르게 설치하고 구성하는 방법을 참조하십시오. 그리고 우리의 JSF 위키 페이지의 섹션 "JSF 설치" .
그러나 아직 JSF 2.2를 사용하지 않고 업그레이드 할 수없는 경우 (이미 Servlet 3.0 호환 컨테이너에있을 때 수월해야 함) 아래 PrimeFaces 파일 업로드 필터를 수동으로 등록해야합니다 web.xml
(멀티 부분 요청을하고 일반 요청 매개 변수 맵을 채워 FacesServlet
평소처럼 계속 작업 할 수 있도록합니다 .)
<filter>
<filter-name>primeFacesFileUploadFilter</filter-name>
<filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>primeFacesFileUploadFilter</filter-name>
<servlet-name>facesServlet</servlet-name>
</filter-mapping>
의 <servlet-name>
값은 동일한 facesServlet
의 <servlet>
항목에있는 값과 정확히 일치해야합니다 . 예를 들어 이면 일치하도록 적절히 편집해야합니다.javax.faces.webapp.FacesServlet
web.xml
Faces Servlet
PrimeFaces 4.x
PrimeFaces 5.x와 동일한 이야기가 4.x에도 적용됩니다.
에 의해 업로드 된 파일 콘텐츠를 가져 오는 데는 잠재적 인 문제 만 있습니다 UploadedFile#getContents()
. null
Apache Commons FileUpload 대신 네이티브 API를 사용할 때 반환 됩니다. UploadedFile#getInputStream()
대신 사용해야 합니다. p : fileUpload에서 업로드 된 이미지를 MySQL에서 BLOB로 삽입하는 방법 도 참조하십시오 .
네이티브 API의 또 다른 잠재적 인 문제는 업로드 구성 요소를 처리하지 않는 다른 "일반"ajax 요청이 실행되는 양식에 업로드 구성 요소가있는 경우입니다. PrimeFaces 4.0 / JSF 2.2.x-javax.servlet.ServletException : The request content-type is not a multipart / form-data에서 파일 업로드가 AJAX에서 작동하지 않음을 참조하십시오 .
두 문제 모두 Apache Commons FileUpload로 전환하여 해결할 수도 있습니다. 자세한 내용은 PrimeFaces 3.x 섹션을 참조하십시오.
PrimeFaces 3.x
This version does not support JSF 2.2 / Servlet 3.0 native file upload. You need to manually install Apache Commons FileUpload and explicitly register the file upload filter in web.xml
.
You need the following libraries:
Those must be present in the webapp's runtime classpath. When using Maven, make sure they are at least runtime scoped (default scope of compile is also good). When manually carrying around JARs, make sure they end up in /WEB-INF/lib
folder.
The file upload filter registration detail can be found in PrimeFaces 5.x section here above. In case you're using PrimeFaces 4+ and you'd like to explicitly use Apache Commons FileUpload instead of JSF 2.2 / Servlet 3.0 native file upload, then you need next to the mentioned libraries and filter also the below context param in web.xml
:
<context-param>
<param-name>primefaces.UPLOADER</param-name>
<param-value>commons</param-value><!-- Allowed values: auto, native and commons. -->
</context-param>
Troubleshooting
In case it still doesn't work, here are another possible causes unrelated to PrimeFaces configuration:
Only if you're using the PrimeFaces file upload filter: There's another
Filter
in your webapp which runs before the PrimeFaces file upload filter and has already consumed the request body by e.g. callinggetParameter()
,getParameterMap()
,getReader()
, etcetera. A request body can be parsed only once. When you call one of those methods before the file upload filter does its job, then the file upload filter will get an empty request body.To fix this, you'd need to put the
<filter-mapping>
of the file upload filter before the other filter inweb.xml
. If the request is not amultipart/form-data
request, then the file upload filter will just continue as if nothing happened. If you use filters that are automagically added because they use annotations (e.g. PrettyFaces), you might need to add explicit ordering via web.xml. See How to define servlet filter order of execution using annotations in WAROnly if you're using the PrimeFaces file upload filter: There's another
Filter
in your webapp which runs before the PrimeFaces file upload filter and has performed aRequestDispatcher#forward()
call. Usually, URL rewrite filters such as PrettyFaces do this. This triggers theFORWARD
dispatcher, but filters listen by default onREQUEST
dispatcher only.To fix this, you'd need to either put the PrimeFaces file upload filter before the forwarding filter, or to reconfigure the PrimeFaces file upload filter to listen on
FORWARD
dispatcher too:<filter-mapping> <filter-name>primeFacesFileUploadFilter</filter-name> <servlet-name>facesServlet</servlet-name> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> </filter-mapping>
There's a nested
<h:form>
. This is illegal in HTML and the browser behavior is unspecified. More than often, the browser won't send the expected data on submit. Make sure that you are not nesting<h:form>
. This is completely regardless of the form'senctype
. Just do not nest forms at all.
If you're still having problems, well, debug the HTTP traffic. Open the webbrowser's developer toolset (press F12 in Chrome/Firebug23+/IE9+) and check the Net/Network section. If the HTTP part looks fine, then debug the JSF code. Put a breakpoint on FileUploadRenderer#decode()
and advance from there.
Saving uploaded file
After you finally got it to work, your next question shall probably be like "How/where do I save the uploaded file?". Well, continue here: How to save uploaded file in JSF.
You are using prettyfaces too? Then set dispatcher to FORWARD:
<filter-mapping>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
One point I noticed with Primefaces 3.4 and Netbeans 7.2:
Remove the Netbeans auto-filled parameters for function handleFileUpload i.e. (event) otherwise event could be null.
<h:form>
<p:fileUpload fileUploadListener="#{fileUploadController.handleFileUpload(event)}"
mode="advanced"
update="messages"
sizeLimit="100000"
allowTypes="/(\.|\/)(gif|jpe?g|png)$/"/>
<p:growl id="messages" showDetail="true"/>
</h:form>
Looks like javax.faces.SEPARATOR_CHAR must not be equal to _
I had same issue with primefaces 5.3 and I went through all the points described by BalusC with no result. I followed his advice of debugging FileUploadRenderer#decode() and I discovered that my web.xml was unproperly set
<context-param>
<param-name>primefaces.UPLOADER</param-name>
<param-value>auto|native|commons</param-value>
</context-param>
The param-value must be 1 of these 3 values but not all of them!! The whole context-param section can be removed and the default will be auto
bean.xhtml
<h:form enctype="multipart/form-data">
<p:outputLabel value="Choose your file" for="submissionFile" />
<p:fileUpload id="submissionFile"
value="#{bean.file}"
fileUploadListener="#{bean.uploadFile}" mode="advanced"
auto="true" dragDropSupport="false" update="messages"
sizeLimit="100000" fileLimit="1" allowTypes="/(\.|\/)(pdf)$/" />
</h:form>
Bean.java
@ManagedBean
@ViewScoped public class Submission implements Serializable {
private UploadedFile file;
//Gets
//Sets
public void uploadFasta(FileUploadEvent event) throws FileNotFoundException, IOException, InterruptedException {
String content = IOUtils.toString(event.getFile().getInputstream(), "UTF-8");
String filePath = PATH + "resources/submissions/" + nameOfMyFile + ".pdf";
MyFileWriter.writeFile(filePath, content);
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO,
event.getFile().getFileName() + " is uploaded.", null);
FacesContext.getCurrentInstance().addMessage(null, message);
}
}
web.xml
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<filter>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
Neither of the suggestions here were helpful for me. So I had to debug primefaces and found the reason of the problem was:
java.lang.IllegalStateException: No multipart config for servlet fileUpload
Then I have added section into my faces servlet in the web.xml. So that has fixed the problem:
<servlet>
<servlet-name>main</servlet-name>
<servlet-class>org.apache.myfaces.webapp.MyFacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<multipart-config>
<location>/tmp</location>
<max-file-size>20848820</max-file-size>
<max-request-size>418018841</max-request-size>
<file-size-threshold>1048576</file-size-threshold>
</multipart-config>
</servlet>
I had the same issue, due to the fact that I had all the configuration that describe in this post, but in my case was because I had two jquery imports (one of them was primefaces's query) which caused conflicts to upload files.
See Primefaces Jquery conflict
For people using Tomee or Tomcat and can't get it working, try to create context.xml in META-INF and add allowCasualMultipartParsing="true"
<?xml version="1.0" encoding="UTF-8"?>
<Context allowCasualMultipartParsing="true">
<!-- empty or not depending your project -->
</Context>
'Programming' 카테고리의 다른 글
Visual Studio 2017에는 템플릿이 없습니다. (0) | 2020.08.23 |
---|---|
CMake에서 경고 수준을 설정하는 방법은 무엇입니까? (0) | 2020.08.23 |
@ Html.ActionLink MVC 4에서 컨트롤러로 매개 변수 전달 (0) | 2020.08.22 |
문자열에서 마지막 세 문자 제거 (0) | 2020.08.22 |
composer를 실행할 때 xdebug 비활성화 (0) | 2020.08.22 |