Khaled
Khaled

Reputation: 8583

Java: Send email with attachment using Oreilly MultipartRequest servlet

I'm using Oreilly MultipartRequest servlet to parse a forms multipart/form-data request as so:

String path = getServletContext().getRealPath("/tmp");
List uploadFiles = new ArrayList();
MultipartRequest multi  = new MultipartRequest(request, path, 50 * 1024 * 1024, "UTF-8");
Enumeration<String> params = multi.getParameterNames();
Enumeration<String> files = multi.getFileNames();
//retrieve text parameters
String param;
while(params .hasMoreElements()){
    param = params .nextElement();
    for(String occurence : multi.getParameterValues(param)){
        pageContext.setAttribute(param, occurence);
    }
}
//get files
String fileParam;
while(files.hasMoreElements()){
    fileParam = files.nextElement();
        uploadFiles.add(multi.getFile(fileParam));
}

I'm able to get all the data, but in regards of files, I want to send them as an attachment, typically this is done as such (by parsing the request)

        ServletFileUpload servletFileUpload = new ServletFileUpload(new DiskFileItemFactory());
        try {
            List fileItemsList = servletFileUpload.parseRequest(request);
            Iterator it = fileItemsList.iterator();
            while (it.hasNext()){
                FileItem fileItem = (FileItem)it.next();
                if (fileItem.isFormField()){
                    messageBodyPart = new MimeBodyPart();
                    DataSource source = new FileDataSource(fileItem.getString());
                    messageBodyPart.setDataHandler(new DataHandler(source));
                    messageBodyPart.setFileName(fileItem.getFieldName());
                    multipart.addBodyPart(messageBodyPart);
                }
            }
        } catch(Exception e) {
            out.println(e.toString());
        }

Instead, I am creating a list of all files uploadFiles to upload. The problem is the attachment uses FileItem interface which allows me to get the contents of the file item as a String using getString(), whereas Oreilly MultipartRequest only returns the file as a File object. How can I use the content of the File Object similarly, or cast it into a FileItem object perhaps.

Upvotes: 1

Views: 133

Answers (2)

Serg M Ten
Serg M Ten

Reputation: 5606

According to the documentation, FileItem.getString() returns "the contents of the file item as a String". But FileDataSource(String) "creates a FileDataSource from the specified path name". So in your second code fragment you are passing a file contents as a String (which who knows what will do for binary files) instead of a file name. And getFieldName() will return the name of the form field and not the name of the upload file (which is what you want).

If you processed the upload with MultipartRequest then it's trivial to instantiate the FileDataSource required by DataHandler from the File objects returned by MultipartRequest.

If you processed the upload with ServletFileUpload then probably the best is to create your own custom implementation of DataSource interface which allows a FileItem in the constructor

public class FileItemDataSource implements DataSource {

    private FileItem item;

    public FileItemDataSource(FileItem item) {
        this.item = item;
    }

    @Override
    public String getContentType() {
        return item.getContentType() ;
    }

    @Override
    public InputStream getInputStream() throws IOException {
        return item.getInputStream();
    }

    @Override
    public String getName() {
        return item.getName();
    }

    @Override
    public OutputStream getOutputStream() throws IOException {
        return item.getOutputStream();
    }
}

with such class you could do

DataSource source = new FileItemDataSource(fileItem);
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName(fileItem.getName());
multipart.addBodyPart(messageBodyPart);

Upvotes: 1

Khaled
Khaled

Reputation: 8583

Apparently the class FileDataSource accepts a File or String at it's constructor. So passing the File object directly simply solves the problem. As such:

    File fileItem = (File)it.next();
    DataSource source = new FileDataSource(fileItem);

Upvotes: 0

Related Questions