J'utilise springboot 2x. Notre projet utilise un Custom HttpServeletRequest qui étend HttpServletRequestWrapper et implémente MultipartHttpServletRequest. Tout fonctionne bien. Mais quand je veux travailler pour le téléchargement de fichiers, il ne peut pas initialiser la requête Multipart. Il montre l'erreur:Comment initialiser la requête Multipart pour HttpServeletRequest personnalisé
java.lang.IllegalStateException: Multipart request not initialized
Ma question est, comment puis-je résoudre cette erreur. Comment la requête Multipart sera initialisée.
Je donne tout le code à ce sujet.
public class XHttpServletRequest extends HttpServletRequestWrapper implements MultipartHttpServletRequest {
public XHttpServletRequest (HttpServletRequest request) {
super(request);
}
private MultiValueMap<String, MultipartFile> multipartFiles;
private String method;
@Override
public String getMethod() {
if (this.method == null) return super.getMethod();
return this.method;
}
public void setMethod(String method) {
this.method = method;
}
private Map<String,String[]> parameters = new LinkedHashMap<String,String[]>();
public void setParameter(String name, String value) {
parameters.put(name, new String[] {value});
}
@Override
public String getParameter(String name) {
if (parameters.get(name) != null) {
return parameters.get(name)[0];
}
HttpServletRequest req = (HttpServletRequest) super.getRequest();
return req.getParameter(name);
}
public Map<String, String[]> getParameterMap() {
Map<String, String[]> result = new LinkedHashMap<String, String[]>();
result.putAll(super.getRequest().getParameterMap());
result.putAll(parameters);
return Collections.<String, String[]>unmodifiableMap(result);
}
public Enumeration<String> getParameterNames() {
Set<String> result = new LinkedHashSet<String>(Collections.list(super.getRequest().getAttributeNames()));
result.addAll(parameters.keySet());
return new Vector<String>(result).elements();
}
public String[] getParameterValues(String name) {
if (parameters.get(name) != null) {
return parameters.get(name);
}
HttpServletRequest req = (HttpServletRequest) super.getRequest();
return req.getParameterValues(name);
}
@Override
public HttpServletRequest getRequest() {
return (HttpServletRequest) super.getRequest();
}
@Override
public HttpMethod getRequestMethod() {
return HttpMethod.resolve(getRequest().getMethod());
}
@Override
public HttpHeaders getRequestHeaders() {
HttpHeaders headers = new HttpHeaders();
Enumeration<String> headerNames = getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
headers.put(headerName, Collections.list(getHeaders(headerName)));
}
return headers;
}
@Override
public HttpHeaders getMultipartHeaders(String s) {
return null;
}
@Override
public Iterator<String> getFileNames() {
return getMultipartFiles().keySet().iterator();
}
@Override
public MultipartFile getFile(String name) {
return getMultipartFiles().getFirst(name);
}
@Override
public List<MultipartFile> getFiles(String name) {
List<MultipartFile> multipartFiles = getMultipartFiles().get(name);
if (multipartFiles != null) {
return multipartFiles;
}
else {
return Collections.emptyList();
}
}
@Override
public Map<String, MultipartFile> getFileMap() {
return getMultipartFiles().toSingleValueMap();
}
@Override
public MultiValueMap<String, MultipartFile> getMultiFileMap() {
return getMultipartFiles();
}
@Override
public String getMultipartContentType(String s) {
return null;
}
/**
* Set a Map with parameter names as keys and list of MultipartFile objects as values.
* To be invoked by subclasses on initialization.
*/
protected final void setMultipartFiles(MultiValueMap<String, MultipartFile> multipartFiles) {
this.multipartFiles =
new LinkedMultiValueMap<>(Collections.unmodifiableMap(multipartFiles));
}
/**
* Obtain the MultipartFile Map for retrieval,
* lazily initializing it if necessary.
* @see #initializeMultipart()
*/
protected MultiValueMap<String, MultipartFile> getMultipartFiles() {
if (this.multipartFiles == null) {
initializeMultipart();
}
return this.multipartFiles;
}
/**
* Lazily initialize the multipart request, if possible.
* Only called if not already eagerly initialized.
*/
protected void initializeMultipart() {
throw new IllegalStateException("Multipart request not initialized");
}
}
Une autre classe étend XHttpServletRequest et c'est au lieu de HttpServeletRequest dans notre projet. Le code suivant:
public class YHttpRequest extends MutableHttpServletRequest {
private ByteArrayOutputStream cachedBytes;
public YHttpRequest(HttpServletRequest request) {
super(request);
}
@Override
public ServletInputStream getInputStream() throws IOException {
if (cachedBytes == null)
cacheInputStream();
return new CachedServletInputStream();
}
@Override
public BufferedReader getReader() throws IOException{
return new BufferedReader(new InputStreamReader(getInputStream()));
}
private void cacheInputStream() throws IOException {
/* Cache the inputstream in order to read it multiple times. For
* convenience, I use apache.commons IOUtils
*/
cachedBytes = new ByteArrayOutputStream();
IOUtils.copy(super.getInputStream(), cachedBytes);
}
public List<Map<String, Object>> getListData() throws RequestException {
List<Map<String, Object>> data = new ArrayList<>();
try {
ObjectMapper mapper = new ObjectMapper();
data = mapper.readValue(this.getInputStream(), new TypeReference<ArrayList<LinkedHashMap>>(){});
System.out.println(data);
}
catch (Exception e) {
// System.out.println(e.)
throw new RequestException("Unable to parse request data", e);
}
return data;
}
private Object cachedData = null;
public Object getRawData() throws RequestException {
Object data = new LinkedHashMap<>();
try {
ObjectMapper mapper = new ObjectMapper();
// data = mapper.readValue(this.getInputStream());
try {
data = mapper.readValue(this.getInputStream(), new TypeReference<HashMap>() {
});
}
catch (JsonMappingException e) {
// e.printStackTrace();
}
try {
data = mapper.readValue(this.getInputStream(), new TypeReference<List<HashMap>>() {
});
}
catch (JsonMappingException e) {
// e.printStackTrace();
}
System.out.println(data);
}
catch (Exception e) {
// System.out.println(e.)
throw new RequestException("Unable to parse request data", e);
}
return data;
}
public Object getData() throws RequestException {
if (this.cachedData == null) {
this.cachedData = this.getRawData();
}
return this.cachedData;
}
/* An inputstream which reads the cached request body */
public class CachedServletInputStream extends ServletInputStream {
private ByteArrayInputStream input;
public CachedServletInputStream() {
/* create a new input stream from the cached request body */
input = new ByteArrayInputStream(cachedBytes.toByteArray());
}
@Override
public boolean isFinished() {
return input.available() == 0;
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setReadListener(ReadListener readListener) {
// throw new IOException("zubair says: Method not implemented in Cached Servlet Input Stream class");
}
@Override
public int read() throws IOException {
return input.read();
}
}
// Storage for Path variable
private Map<String, Object> pathVariableMap = null;
public Map<String, Object> getPathVariableMap() {
if (this.pathVariableMap == null) {
this.pathVariableMap = new LinkedHashMap<>();
this.pathVariableMap.putAll((Map<? extends String, ?>) this.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE));
}
return this.pathVariableMap;
}
public Object getPathVariable(String key) {
return this.getPathVariableMap().get(key);
}
public FurinaHttpRequest setPathVariable(String key, Object value) {
this.getPathVariableMap().put(key, value);
return this;
}
public FurinaHttpRequest clearPathVariableMap() {
this.getPathVariableMap().clear();
return this;
}
}
Le code du contrôleur:
public String handleFileUpload(YHttpRequest request) {
if (request.getMethod().equalsIgnoreCase("GET")){
return "{}";
}
Map<String, MultipartFile> file= request.getFileMap();
try {
for(Map.Entry<String, MultipartFile> entry : file.entrySet()){
storageService.store(entry.getValue());
//model.addAttribute("message", "You successfully uploaded " + entry.getValue().getOriginalFilename() + "!");
files.add(entry.getValue().getOriginalFilename());
}
} catch (Exception e) {
//model.addAttribute("message", "FAIL to upload !");
}
return "{}";
}
Avez-vous enregistré explicitement MutliPartResolver? Par ailleurs, pourquoi la méthode _initializeMultipart_ renvoie-t-elle une exception à la fois? – Matt