Issue Details (XML | Word | Printable)

Key: SERVLET_SPEC-57
Type: Improvement Improvement
Status: Resolved Resolved
Resolution: Fixed
Priority: Major Major
Assignee: Shing Wai Chan
Reporter: Nick Williams
Votes: 3
Watchers: 2
Operations

If you were logged in you would be able to see more operations.
servlet-spec

Add getFileName() method to javax.servlet.http.Part

Created: 18/Feb/13 06:52 PM   Updated: 01/Mar/13 12:21 AM   Resolved: 01/Mar/13 12:21 AM
Component/s: None
Affects Version/s: None
Fix Version/s: None

Time Tracking:
Original Estimate: 2 hours
Original Estimate - 2 hours
Remaining Estimate: 2 hours
Remaining Estimate - 2 hours
Time Spent: Not Specified
Time Spent - Not Specified

Environment:

All


Tags: HttpServletRequest Part file_upload filename
Participants: carojkov, markt_asf, Nick Williams and Shing Wai Chan


 Description  « Hide

The javax.servlet.http.Part interface lacks a method for retrieving the file name of a part. Most request parts have file names, typically provided by the client's browser as the name of the file on the client's file system when the file is uploaded through the form submission. Currently, consumers of Part must create their own method to extract the file name:

public static String getFileName(Part filePart)
{
    String header = filePart.getHeader("content-disposition");
    for(String headerPart : header.split(";"))
    {
        if(headerPart.trim().startsWith("filename"))
        {
            return headerPart.substring(headerPart.indexOf('=') + 1).trim()
                             .replace("\"", "");
        }
    }
    return null;
}

Tomcat, as an example, already has a method to extract the file name in its Part implementation, but since it is not exposed via the public Part interface developers cannot use it without limiting the portability of their applications. It's possible other containers already do something similar.

The suggested getFileName() method should:

  • Locate the Content-Disposition header from the Part. If no such header exists, return null.
  • Extract the filename attribute from the Content-Disposition header and return its value trimmed.
  • If no filename attribute exists or the filename attribute value is null, return null.
  • Not throw any exceptions.

Estimate 5 minutes to add the method to the interface and < 2 hours to add relevant documentation regarding the method to the spec.



Shing Wai Chan added a comment - 01/Mar/13 12:21 AM

Add a method Part#getSubmittedFileName

Sending src/main/java/javax/servlet/http/Part.java
Transmitting file data .
Committed revision 59926.


Nick Williams added a comment - 20/Feb/13 03:35 PM - edited

By the way, Mark, if this gets accepted for 3.1 I'll implement it in Tomcat. Should just be a matter of adding the method to the interface and then implementing the method in ApplicationPart to wrap ApplicationPart#getFilename().


markt_asf added a comment - 18/Feb/13 07:23 PM

+1


Nick Williams added a comment - 18/Feb/13 07:18 PM

I agree. I prefer getSubmittedFileName(). Seems the most applicable, as that's exactly what it is: nothing more or less than the submitted file name.


carojkov added a comment - 18/Feb/13 07:15 PM

I'd like to propose a method name that clearly states that this is a file name specified by the client. e.g. getClientFileName(). getRequestedFileName() or getSubmittedFileName(). This should help avoid confusion if/when it's decided if adding another get*File() method to the Part is needed. i.e. getFile() returning File after a call to Part#write(String) method.


Nick Williams added a comment - 18/Feb/13 06:59 PM - edited

Note that the sample code submitted does not follow the second part of rule 1, "If no such header exists, return null." A more stable implementation would be:

public static String getFileName(Part filePart)
{
    String header = filePart.getHeader("content-disposition");
    if(header == null)
        return null;
    for(String headerPart : header.split(";"))
    {
        if(headerPart.trim().startsWith("filename"))
        {
            return headerPart.substring(headerPart.indexOf('=') + 1).trim()
                             .replace("\"", "");
        }
    }
    return null;
}

Of course, this is merely a sample implementation, and container developers are free to implement the spec in their own way.