001/* 002 * Copyright 2002-2020 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.web.multipart.support; 018 019import java.io.ByteArrayInputStream; 020import java.io.IOException; 021import java.io.InputStream; 022import java.nio.charset.Charset; 023import javax.servlet.http.HttpServletRequest; 024 025import org.springframework.http.HttpHeaders; 026import org.springframework.http.MediaType; 027import org.springframework.http.server.ServerHttpRequest; 028import org.springframework.http.server.ServletServerHttpRequest; 029import org.springframework.web.multipart.MultipartException; 030import org.springframework.web.multipart.MultipartFile; 031import org.springframework.web.multipart.MultipartHttpServletRequest; 032import org.springframework.web.multipart.MultipartResolver; 033 034/** 035 * {@link ServerHttpRequest} implementation that accesses one part of a multipart 036 * request. If using {@link MultipartResolver} configuration the part is accessed 037 * through a {@link MultipartFile}. Or if using Servlet 3.0 multipart processing 038 * the part is accessed through {@code ServletRequest.getPart}. 039 * 040 * @author Rossen Stoyanchev 041 * @author Juergen Hoeller 042 * @since 3.1 043 */ 044public class RequestPartServletServerHttpRequest extends ServletServerHttpRequest { 045 046 private final MultipartHttpServletRequest multipartRequest; 047 048 private final String requestPartName; 049 050 private final HttpHeaders multipartHeaders; 051 052 053 /** 054 * Create a new {@code RequestPartServletServerHttpRequest} instance. 055 * @param request the current servlet request 056 * @param requestPartName the name of the part to adapt to the {@link ServerHttpRequest} contract 057 * @throws MissingServletRequestPartException if the request part cannot be found 058 * @throws MultipartException if MultipartHttpServletRequest cannot be initialized 059 */ 060 public RequestPartServletServerHttpRequest(HttpServletRequest request, String requestPartName) 061 throws MissingServletRequestPartException { 062 063 super(request); 064 065 this.multipartRequest = MultipartResolutionDelegate.asMultipartHttpServletRequest(request); 066 this.requestPartName = requestPartName; 067 068 HttpHeaders multipartHeaders = this.multipartRequest.getMultipartHeaders(requestPartName); 069 if (multipartHeaders == null) { 070 throw new MissingServletRequestPartException(requestPartName); 071 } 072 this.multipartHeaders = multipartHeaders; 073 } 074 075 076 @Override 077 public HttpHeaders getHeaders() { 078 return this.multipartHeaders; 079 } 080 081 @Override 082 public InputStream getBody() throws IOException { 083 // Prefer Servlet Part resolution to cover file as well as parameter streams 084 if (this.multipartRequest instanceof StandardMultipartHttpServletRequest) { 085 try { 086 return this.multipartRequest.getPart(this.requestPartName).getInputStream(); 087 } 088 catch (Exception ex) { 089 throw new MultipartException("Failed to retrieve request part '" + this.requestPartName + "'", ex); 090 } 091 } 092 093 // Spring-style distinction between MultipartFile and String parameters 094 MultipartFile file = this.multipartRequest.getFile(this.requestPartName); 095 if (file != null) { 096 return file.getInputStream(); 097 } 098 String paramValue = this.multipartRequest.getParameter(this.requestPartName); 099 if (paramValue != null) { 100 return new ByteArrayInputStream(paramValue.getBytes(determineEncoding())); 101 } 102 103 throw new IllegalStateException("No body available for request part '" + this.requestPartName + "'"); 104 } 105 106 private String determineEncoding() { 107 MediaType contentType = getHeaders().getContentType(); 108 if (contentType != null) { 109 Charset charset = contentType.getCharset(); 110 if (charset != null) { 111 return charset.name(); 112 } 113 } 114 String encoding = this.multipartRequest.getCharacterEncoding(); 115 return (encoding != null ? encoding : FORM_CHARSET); 116 } 117 118}