All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.blade.web.multipart.Multipart Maven / Gradle / Ivy

There is a newer version: 1.7.2-beta
Show newest version
/**
 * Copyright (c) 2015, biezhi 王爵 ([email protected])
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * 	http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.blade.web.multipart;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import blade.kit.IOKit;

/**
 * 
 * 

* Multipart对象 *

* * @author biezhi * @since 1.0 */ public class Multipart { public static final String CONTENT_TYPE = "Content-Type"; public static final String CONTENT_DISPOSITION = "Content-Disposition"; public static final String CONTENT_LENGTH = "Content-Length"; public static final String FORM_DATA = "form-data"; public static final String ATTACHMENT = "attachment"; public static final String MULTIPART = "multipart/"; public static final String MULTIPART_MIXED = "multipart/mixed"; public static boolean isMultipartContent(HttpServletRequest request) { if (!"post".equals(request.getMethod().toLowerCase())) { return false; } String contentType = request.getContentType(); if (contentType == null) { return false; } if (contentType.toLowerCase().startsWith(MULTIPART)) { return true; } return false; } public void parse(HttpServletRequest request, MultipartHandler partHandler) throws IOException, MultipartException { if (!isMultipartContent(request)) { throw new MultipartException("Not a multipart content. The HTTP method should be 'POST' and the " + "Content-Type 'multipart/form-data' or 'multipart/mixed'."); } InputStream inputStream = request.getInputStream(); String contentType = request.getContentType(); String charEncoding = request.getCharacterEncoding(); byte[] boundary = getBoundary(contentType); if (boundary == null) { throw new MultipartException("the request was rejected because no multipart boundary was found"); } // create a multipart reader MultipartReader multipartReader = new MultipartReader(inputStream, boundary); multipartReader.setHeaderEncoding(charEncoding); String currentFieldName = null; boolean skipPreamble = true; for (;;) { boolean nextPart; if (skipPreamble) { nextPart = multipartReader.skipPreamble(); } else { nextPart = multipartReader.readBoundary(); } if (!nextPart) { if (currentFieldName == null) { // outer multipart terminated -> no more data return; } // inner multipart terminated -> return to parsing the outer multipartReader.setBoundary(boundary); currentFieldName = null; continue; } String headersString = multipartReader.readHeaders(); Map headers = getHeadersMap(headersString); if (currentFieldName == null) { // we're parsing the outer multipart String fieldName = getFieldName( headers.get(CONTENT_DISPOSITION) ); if (fieldName != null) { String partContentType = headers.get(CONTENT_TYPE); if (partContentType != null && partContentType.toLowerCase().startsWith(MULTIPART_MIXED)) { // multiple files associated with this field name currentFieldName = fieldName; multipartReader.setBoundary( getBoundary(partContentType)); skipPreamble = true; continue; } String fileName = getFileName( headers.get(CONTENT_DISPOSITION) ); if (fileName == null) { // call the part handler String value = IOKit.toString(multipartReader.newInputStream()); partHandler.handleFormItem(fieldName, value); } else { // create the temp file File tempFile = createTempFile(multipartReader); // call the part handler FileItem fileItem = new FileItem(fieldName, fileName, partContentType, tempFile.length(), tempFile, headers); partHandler.handleFileItem(fieldName, fileItem); } continue; } } else { String fileName = getFileName( headers.get(CONTENT_DISPOSITION) ); String partContentType = headers.get(CONTENT_TYPE); if (fileName != null) { // create the temp file File tempFile = createTempFile(multipartReader); // call the part handler FileItem fileItem = new FileItem(currentFieldName, fileName, partContentType, tempFile.length(), tempFile, headers); partHandler.handleFileItem(currentFieldName, fileItem); continue; } } multipartReader.discardBodyData(); } } private File createTempFile(MultipartReader multipartReader) throws IOException { File tempFile = File.createTempFile("com.blade.file_", null); FileOutputStream outputStream = null; try { outputStream = new FileOutputStream(tempFile); copy( multipartReader.newInputStream(), outputStream ); } finally { if (outputStream != null) { try { outputStream.close(); } catch (Exception e) {} } } return tempFile; } private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; private static final int EOF = -1; private long copy(InputStream input, OutputStream output) throws IOException { long count = 0; int n = 0; byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; while (EOF != (n = input.read(buffer))) { output.write(buffer, 0, n); count += n; } return count; } protected Map getHeadersMap(String headerPart) { final int len = headerPart.length(); final Map headers = new HashMap(); int start = 0; for (;;) { int end = parseEndOfLine(headerPart, start); if (start == end) { break; } String header = headerPart.substring(start, end); start = end + 2; while (start < len) { int nonWs = start; while (nonWs < len) { char c = headerPart.charAt(nonWs); if (c != ' ' && c != '\t') { break; } ++nonWs; } if (nonWs == start) { break; } // continuation line found end = parseEndOfLine(headerPart, nonWs); header += " " + headerPart.substring(nonWs, end); start = end + 2; } // parse header line final int colonOffset = header.indexOf(':'); if (colonOffset == -1) { // this header line is malformed, skip it. continue; } String headerName = header.substring(0, colonOffset).trim(); String headerValue = header.substring(header.indexOf(':') + 1).trim(); if (headers.containsKey(headerName)) { headers.put( headerName, headers.get(headerName) + "," + headerValue ); } else { headers.put(headerName, headerValue); } } return headers; } private int parseEndOfLine(String headerPart, int end) { int index = end; for (;;) { int offset = headerPart.indexOf('\r', index); if (offset == -1 || offset + 1 >= headerPart.length()) { throw new IllegalStateException("Expected headers to be terminated by an empty line."); } if (headerPart.charAt(offset + 1) == '\n') { return offset; } index = offset + 1; } } private String getFieldName(String contentDisposition) { String fieldName = null; if (contentDisposition != null && contentDisposition.toLowerCase().startsWith(FORM_DATA)) { ParameterParser parser = new ParameterParser(); parser.setLowerCaseNames(true); // parameter parser can handle null input Map params = parser.parse(contentDisposition, ';'); fieldName = (String) params.get("name"); if (fieldName != null) { fieldName = fieldName.trim(); } } return fieldName; } protected byte[] getBoundary(String contentType) { ParameterParser parser = new ParameterParser(); parser.setLowerCaseNames(true); // Parameter parser can handle null input Map params = parser.parse(contentType, new char[] {';', ','}); String boundaryStr = (String) params.get("boundary"); if (boundaryStr == null) { return null; } byte[] boundary; try { boundary = boundaryStr.getBytes("ISO-8859-1"); } catch (UnsupportedEncodingException e) { boundary = boundaryStr.getBytes(); } return boundary; } private String getFileName(String contentDisposition) { String fileName = null; if (contentDisposition != null) { String cdl = contentDisposition.toLowerCase(); if (cdl.startsWith(FORM_DATA) || cdl.startsWith(ATTACHMENT)) { ParameterParser parser = new ParameterParser(); parser.setLowerCaseNames(true); // parameter parser can handle null input Map params = parser.parse(contentDisposition, ';'); if (params.containsKey("filename")) { fileName = (String) params.get("filename"); if (fileName != null) { fileName = fileName.trim(); } else { // even if there is no value, the parameter is present, // so we return an empty file name rather than no file // name. fileName = ""; } } } } return fileName; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy