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

com.cybermkd.upload.MultipartRequest Maven / Gradle / Ivy

package com.cybermkd.upload;

import com.cybermkd.common.http.HttpRequest;
import com.cybermkd.common.http.UploadedFile;
import com.cybermkd.common.http.exception.WebException;
import com.cybermkd.common.util.Lister;
import com.cybermkd.common.util.stream.FileRenamer;
import com.cybermkd.log.Logger;
import com.cybermkd.upload.multipart.FilePart;
import com.cybermkd.upload.multipart.MultipartParser;
import com.cybermkd.upload.multipart.ParamPart;
import com.cybermkd.upload.multipart.Part;

import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import java.util.Vector;

/**
 * A utility class to handle multipart/form-data requests,
 * the kind of requests that support file uploads.  This class emulates the
 * interface of HttpRequest, making it familiar to use.
 * It uses a "push" model where any incoming files are read and saved directly
 * to disk in the constructor. If you wish to have more flexibility, e.g.
 * write the files to a database, use the "pull" model
 * MultipartParser instead.
 * 

* This class can receive arbitrarily large files (up to an artificial limit * you can set), and fairly efficiently too. * It cannot handle nested data (multipart content within multipart content). * It can now with the latest release handle internationalized content * (such as non Latin-1 filenames). *

* To avoid collisions and have fine control over file placement, there's a * constructor variety that takes a pluggable FileRenamePolicy implementation. * A particular policy can choose to rename or change the location of the file * before it's written. *

* See the included upload.war for an example of how to use this class. *

* The full file upload specification is contained in experimental RFC 1867, * available at * http://www.ietf.org/rfc/rfc1867.txt. * * @author Jason Hunter * @author Geoff Soutter * @version 1.0, 1998/09/18
* @see MultipartParser */ public class MultipartRequest { private static final Logger logger = Logger.getLogger(MultipartRequest.class); private static final int DEFAULT_MAX_POST_SIZE = 1024 * 1024; // 1 Meg protected Hashtable> params = new Hashtable>(); // name - Vector of values protected Hashtable files = new Hashtable(); // name - UploadedFile /** * Constructs a new MultipartRequest to handle the specified request, * saving any uploaded files to the given directory, and limiting the * upload size to 1 Megabyte. If the content is too large, an * IOException is thrown. This constructor actually parses the * multipart/form-data and throws an IOException if there's any * problem reading or parsing the request. * * @param request the servlet request. * @param saveDirectory the directory in which to save any uploaded files. * @throws IOException if the uploaded content is larger than 1 Megabyte * or there's a problem reading or parsing the request. */ public MultipartRequest(HttpRequest request, String saveDirectory) throws IOException { this(request, saveDirectory, DEFAULT_MAX_POST_SIZE); } /** * Constructs a new MultipartRequest to handle the specified request, * saving any uploaded files to the given directory, and limiting the * upload size to the specified length. If the content is too large, an * IOException is thrown. This constructor actually parses the * multipart/form-data and throws an IOException if there's any * problem reading or parsing the request. * * @param request the servlet request. * @param saveDirectory the directory in which to save any uploaded files. * @param maxPostSize the maximum size of the POST content. * @throws IOException if the uploaded content is larger than * maxPostSize or there's a problem reading or parsing the request. */ public MultipartRequest(HttpRequest request, String saveDirectory, int maxPostSize) throws IOException { this(request, saveDirectory, maxPostSize, null, null); } /** * Constructs a new MultipartRequest to handle the specified request, * saving any uploaded files to the given directory, and limiting the * upload size to the specified length. If the content is too large, an * IOException is thrown. This constructor actually parses the * multipart/form-data and throws an IOException if there's any * problem reading or parsing the request. * * @param request the servlet request. * @param saveDirectory the directory in which to save any uploaded files. * @param encoding the encoding of the response, such as ISO-8859-1 * @throws IOException if the uploaded content is larger than * 1 Megabyte or there's a problem reading or parsing the request. */ public MultipartRequest(HttpRequest request, String saveDirectory, String encoding) throws IOException { this(request, saveDirectory, DEFAULT_MAX_POST_SIZE, encoding, null); } /** * Constructs a new MultipartRequest to handle the specified request, * saving any uploaded files to the given directory, and limiting the * upload size to the specified length. If the content is too large, an * IOException is thrown. This constructor actually parses the * multipart/form-data and throws an IOException if there's any * problem reading or parsing the request. * * @param request the servlet request. * @param saveDirectory the directory in which to save any uploaded files. * @param maxPostSize the maximum size of the POST content. * @param renamer change file name * @throws IOException if the uploaded content is larger than * maxPostSize or there's a problem reading or parsing the request. */ public MultipartRequest(HttpRequest request, String saveDirectory, int maxPostSize, FileRenamer renamer) throws IOException { this(request, saveDirectory, maxPostSize, null, renamer); } /** * Constructs a new MultipartRequest to handle the specified request, * saving any uploaded files to the given directory, and limiting the * upload size to the specified length. If the content is too large, an * IOException is thrown. This constructor actually parses the * multipart/form-data and throws an IOException if there's any * problem reading or parsing the request. * * @param request the servlet request. * @param saveDirectory the directory in which to save any uploaded files. * @param maxPostSize the maximum size of the POST content. * @param encoding the encoding of the response, such as ISO-8859-1 * @throws IOException if the uploaded content is larger than * maxPostSize or there's a problem reading or parsing the request. */ public MultipartRequest(HttpRequest request, String saveDirectory, int maxPostSize, String encoding) throws IOException { this(request, saveDirectory, maxPostSize, encoding, null); } /** * Constructs a new MultipartRequest to handle the specified request, * saving any uploaded files to the given directory, and limiting the * upload size to the specified length. If the content is too large, an * IOException is thrown. This constructor actually parses the * multipart/form-data and throws an IOException if there's any * problem reading or parsing the request. *

* To avoid file collisions, this constructor takes an implementation of the * FileRenamePolicy interface to allow a pluggable rename policy. * * @param request the servlet request. * @param saveDirectory the directory in which to save any uploaded files. * @param maxPostSize the maximum size of the POST content. * @param encoding the encoding of the response, such as ISO-8859-1 * @param renamer a pluggable file rename policy * @throws IOException if the uploaded content is larger than * maxPostSize or there's a problem reading or parsing the request. */ public MultipartRequest(HttpRequest request, String saveDirectory, int maxPostSize, String encoding, FileRenamer renamer) throws IOException { this(request, new File(saveDirectory), maxPostSize, encoding, renamer, null, null); } /** * Constructs a new MultipartRequest to handle the specified request, * saving any uploaded files to the given directory, and limiting the * upload size to the specified length. If the content is too large, an * IOException is thrown. This constructor actually parses the * multipart/form-data and throws an IOException if there's any * problem reading or parsing the request. *

* To avoid file collisions, this constructor takes an implementation of the * FileRenamePolicy interface to allow a pluggable rename renamer. * * @param request the servlet request. * @param saveDirectory the directory in which to save any uploaded files. * @param maxPostSize the maximum size of the POST content. * @param encoding the encoding of the response, such as ISO-8859-1 * @param renamer a pluggable file rename renamer * @throws IOException if the uploaded content is larger than * maxPostSize or there's a problem reading or parsing the request. */ public MultipartRequest(HttpRequest request, File saveDirectory, int maxPostSize, String encoding, FileRenamer renamer, String[] allows, String[] denieds) throws IOException { // Sanity check values if (request == null) throw new IllegalArgumentException("Request cannot be null."); if (maxPostSize <= 0) { throw new IllegalArgumentException("MaxPostSize must be positive."); } // Check saveDirectory is truly a directory if (!saveDirectory.isDirectory()) throw new IllegalArgumentException("Not a directory: " + saveDirectory); // Check saveDirectory is writable if (!saveDirectory.canWrite()) throw new IOException("Not writable: " + saveDirectory); // Parse the incoming multipart, storing files in the dir provided, // and populate the meta objects which describe what we found MultipartParser parser = new MultipartParser(request, maxPostSize, true, true, encoding); List deniedTypes = Lister.of(denieds); List allowTypes = Lister.of(allows); Part part; FilePart filePart; String name, value, contentType; ParamPart paramPart; Vector existingValues; while ((part = parser.readNextPart()) != null) { name = part.getName(); if (part.isParam()) { // It's a parameter part, add it to the vector of values paramPart = (ParamPart) part; value = paramPart.getStringValue(); existingValues = (Vector) params.get(name); if (existingValues == null) { existingValues = new Vector(); params.put(name, existingValues); } existingValues.addElement(value); } else if (part.isFile()) { // It's a file part filePart = (FilePart) part; contentType = filePart.getContentType(); if ((allowTypes.size() > 0 && !allowTypes.contains(contentType)) || (deniedTypes.size() > 0 && deniedTypes.contains(contentType))) { throw new WebException("Denied upload file type '" + filePart.getContentType() + "'."); //continue; } String fileName = filePart.getFileName(); if (fileName != null) { filePart.setRenamer(renamer); // null renamer is OK // The part actually contained a file filePart.writeTo(saveDirectory); files.put(name, new UploadedFile(filePart.getDir().toString(), filePart.getFileName(), fileName, filePart.getContentType())); logger.info("Upload success. file \"%s\" type \"%s\"", filePart.getFileName(), filePart.getContentType()); } else { // The field did not contain a file files.put(name, new UploadedFile(null, null, null, null)); logger.warn("Upload empty file %s.", name); } } } } /** * Returns the names of all the uploaded files as an Enumeration of * Strings. It returns an empty Enumeration if there are no uploaded * files. Each file name is the name specified by the form, not by * the user. * * @return the names of all the uploaded files as an Enumeration of Strings. */ public Enumeration getFileNames() { return files.keys(); } /** * Returns the filesystem name of the specified file, or null if the * file was not included in the upload. A filesystem name is the name * specified by the user. It is also the name under which the file is * actually saved. * * @param name the file name. * @return the filesystem name of the file. */ public String getFilesystemName(String name) { try { UploadedFile file = files.get(name); return file.getFileName(); // may be null } catch (Exception e) { return null; } } /** * Returns the original filesystem name of the specified file (before any * renaming policy was applied), or null if the file was not included in * the upload. A filesystem name is the name specified by the user. * * @param name the file name. * @return the original file name of the file. */ public String getOriginalFileName(String name) { try { UploadedFile file = files.get(name); return file.getOriginalFileName(); // may be null } catch (Exception e) { return null; } } /** * Returns the content type of the specified file (as supplied by the * client browser), or null if the file was not included in the upload. * * @param name the file name. * @return the content type of the file. */ public String getContentType(String name) { try { UploadedFile file = files.get(name); return file.getContentType(); // may be null } catch (Exception e) { return null; } } /** * Returns a File object for the specified file saved on the server's * filesystem, or null if the file was not included in the upload. * * @param name the file name. * @return a File object for the named file. */ public File getFile(String name) { try { UploadedFile file = files.get(name); return file.getFile(); // may be null } catch (Exception e) { return null; } } /** * Returns all File objects for the specified file saved on the server's * filesystem * * @return a File objects. */ public Hashtable getFiles() { return files; } /** * Returns all Param objects for the specified param saved on the server's * filesystem * * @return a Param objects. */ public Hashtable> getParams() { return params; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy