users@jersey.java.net

Problem saving binary data using Jersey multipart

From: Geoff Sallee <geoff.sallee_at_gmail.com>
Date: Thu, 29 Jan 2009 17:02:45 -0800

Hello,

I just integrated the jersey-multipart-1.0.1 library into my Jersey project
in order to more easily handle file uploads. The problem is that when I
attempt to save the file using the InputStream retrieved from
multiPart.getBodyParts().get(0) (there is only one part in my test form) it
only saves part of the file to disk. For example, if I attempt to upload a
92KB JPEG image it only gets saved as an 8KB JPEG, which only contains the
top portion of the image. Here is the code I am using:

public Response addUserAsset(
            @PathParam("userName") String userName,
            MultiPart multiPart) {
        String relativePath = null;
        String mimeType = null;
        String fileName = null;
        try {
            InputStream inputStream = null;
            for(BodyPart bodyPart : multiPart.getBodyParts()) {
                mimeType = bodyPart.getHeaders().getFirst("Content-Type");
                if(!StringUtils.isEmpty(mimeType) &&
mimeType.startsWith("image")) {
                    String metaData =
bodyPart.getHeaders().getFirst("Content-Disposition");
                    Matcher m = fileNamePattern.matcher(metaData);
                    if(m.matches()) {
                        fileName = m.group(1);
                    }
                    BodyPartEntity bpe = (BodyPartEntity)
bodyPart.getEntity();
                    inputStream = bpe.getInputStream();
                    break;
                }
            }

            if(inputStream != null) {
                String baseDirPath =
servletContext.getInitParameter("USER_DIGITAL_ASSET_DIR_PATH");
                DigitalAssetAccess access = new
DigitalAssetAccessImpl(baseDirPath);
                relativePath = access.store(userName, fileName, mimeType,
inputStream); //THIS METHOD ACTUALLY STORES THE FILE TO DISK
            }
            else {
                result.setSuccess(false);
                result.addMessage(INVALID_VALUE);
                return ResponseUtil.buildResponse(Status.BAD_REQUEST,
result);
            }
        }
        catch(IOException ioe) {
            result.setSuccess(false);
            result.addMessage(INTERNAL_SERVER_ERROR);
            return ResponseUtil.buildResponse(Status.INTERNAL_SERVER_ERROR,
result);
        }
        catch(Exception e) {
            result.setSuccess(false);
            result.addMessage(INTERNAL_SERVER_ERROR);
            return ResponseUtil.buildResponse(Status.INTERNAL_SERVER_ERROR,
result);
        }
}

My store method uses the InputStream as follows:

public String store(String userLoginId, String fileName,
            String mimeType, InputStream inputStream) throws IOException {

        File parentDir = new File(baseDirPath + "/" + userLoginId);
        if (!parentDir.exists()) {
            parentDir.mkdirs();
        }

        String assetFileName = getUniqueName(fileName, mimeType);

        File assetFile = new File(parentDir, assetFileName);
        if (assetFile.exists()) {
            throw new IllegalStateException(
                    "File already exists with the name:" + assetFileName);
        } else {
            assetFile.createNewFile();
        }

        OutputStream outputStream = new BufferedOutputStream(
                new FileOutputStream(assetFile), BUFFER_SIZE); //
BUFFER_SIZE is 1024 * 1024 * 2 (2MB)

        int b;
        while ((b = inputStream.read()) != EOF) { // EOF is -1
            outputStream.write(b);
        }
        inputStream.close();
        outputStream.flush();
        outputStream.close();

        return userLoginId + "/" + assetFileName;
    }

I have also tested storing the file using the javax.ImageIO package with the
same results, so I can't imagine it's due to the way the file is being
stored. Am I missing something important? I did notice the mention of
calling multipart.cleanup() but that had no effect in my case. Right now it
looks like the files that are being stored are exactly 8KB so I'm thinking
it has something to do with the threshold value, but I'm not sure what I can
do to fix it. Any help is appreciated.

Regards,
Geoff