commons-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Brian Pontarelli <br...@pontarelli.com>
Subject Re: [Fileupload] Missing character in the middle of a file
Date Tue, 12 Oct 2010 21:15:52 GMT
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> Brian,
> 
> On 10/4/2010 11:43 AM, Brian Pontarelli wrote:
>> I figured that the original File and the File written out by the
>> FileUpload would have different bytes at the start or end and it was
>> my mock input stream that was causing the issue. To test this theory
>> I opened both files in a HEX editor. What I found was that the files
>> differ by one a single byte and that byte is at position 305. The
>> other interesting thing I found was that the byte that exists in the
>> original and is missing from the FileUpload file is 'FF'.
> 
> That's weird. Is the missing byte always at position 305? What variety
> of "test" files have you tried? Is it always 0xff that gets discarded?
> 
> Could you post some of your test driver code, and some of the servlet
> code so we can see how they interact?

I'm back from my travels and wanted to circle back on this thread. There is quite a bit of
code for all of this stuff, but I'll post some of it. I'm going to post the code we use to
create the multipart request and some unit test code we use to test it all:

public class MultipartInputStream extends ServletInputStream {
    public static final byte[] BOUNDARY = getBytes("--jcatapultmultipartuploadLKAlskld09309djoid");
    public static final byte[] CLOSE_BOUNDARY = getBytes("--");
    public static final byte[] CRLF = getBytes("\r\n");
    public static final byte[] CONTENT_DISPOSITION = getBytes("Content-Disposition: form-data;
name=");
    public static final byte[] CONTENT_TYPE = getBytes("Content-Type: ");
    public static final byte[] CONTENT_TRANSFER_ENCODING = getBytes("Content-Transfer-Encoding:
binary");
    public static final byte[] FILENAME = getBytes("; filename=");
    public static final byte[] QUOTE = getBytes("\"");
    private final byte[] bytes;
    private int index = 0;

    public MultipartInputStream(Map<String, List<String>> parameters, Map<String,
FileInfo> files) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        for (String key : parameters.keySet()) {
            List<String> values = parameters.get(key);
            for (String value : values) {
                baos.write(BOUNDARY);
                baos.write(CRLF);

                // Content disposition header
                baos.write(CONTENT_DISPOSITION);
                baos.write(QUOTE);
                baos.write(getBytes(key));
                baos.write(QUOTE);

                // Header end
                baos.write(CRLF);
                baos.write(CRLF);

                // Data
                baos.write(getBytes(value));

                // End
                baos.write(CRLF);
            }
        }

        for (String key : files.keySet()) {
            FileInfo file = files.get(key);
            // Boundary
            baos.write(BOUNDARY);
            baos.write(CRLF);

            // Content disposition header
            baos.write(CONTENT_DISPOSITION);
            baos.write(QUOTE);
            baos.write(getBytes(key));
            baos.write(QUOTE);
            baos.write(FILENAME);
            baos.write(QUOTE);
            baos.write(getBytes(file.file.getName()));
            baos.write(QUOTE);

            // Content type header
            baos.write(CRLF);
            baos.write(CONTENT_TYPE);
            baos.write(getBytes(file.contentType));

            // Content transfer encoding header
            baos.write(CRLF);
            baos.write(CONTENT_TRANSFER_ENCODING);

            // Header end
            baos.write(CRLF);
            baos.write(CRLF);

            // Data
            byte[] ba = new byte[4096];
            InputStream is = new FileInputStream(file.file);
            int len;
            while ((len = is.read(ba)) != -1) {
                baos.write(ba, 0, len);
            }
            is.close();

            // End
            baos.write(CRLF);
        }

        baos.write(BOUNDARY);
        baos.write(CLOSE_BOUNDARY);
        baos.write(CRLF);
        baos.flush();
        bytes = baos.toByteArray();
    }

    @Override
    public int available() throws IOException {
        return bytes.length;
    }

    public int read() throws IOException {
        if (index == bytes.length) {
            return -1;
        }
        return bytes[index++];
    }

    private static byte[] getBytes(String str) {
        try {
            return str.getBytes("US-ASCII");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }
}

public class FileInfo {
    public final File file;
    public final String name;
    public final String contentType;

    public FileInfo(File file, String name, String contentType) {
        this.file = file;
        this.name = name;
        this.contentType = contentType;
    }

    public File getFile() {
        return file;
    }

    public String getName() {
        return name;
    }

    public String getContentType() {
        return contentType;
    }
}



Unit test code:

@Test
public void multipartJARFile() throws Exception {
    MockHttpServletRequest request = new MockHttpServletRequest("/foo", new MockServletContext());
    request.addFile("file", new File("src/java/test/unit/org/jcatapult/servlet/test.jar"),
"application/java-archive");
    request.setParameter("test", "test");

    FileItemFactory factory = new DiskFileItemFactory();
    ServletFileUpload upload = new ServletFileUpload(factory);
    List<FileItem> items = upload.parseRequest(request);
    assertEquals(2, items.size());
    assertTrue(items.get(0).isFormField());
    assertEquals(items.get(0).getFieldName(), "test");
    assertEquals(items.get(0).getString(), "test");

    assertFalse(items.get(1).isFormField());
    assertEquals(items.get(1).getFieldName(), "file");
    assertEquals(items.get(1).getName(), "test.jar");
    assertEquals(items.get(1).getContentType(), "application/java-archive");

    File file = File.createTempFile("fileuploadtest", ".jar");
    items.get(1).write(file);

    byte[] orig = read(new File("src/java/test/unit/org/jcatapult/servlet/test.jar"));
    byte[] read = read(file);

    assertEquals(orig.length, read.length);
    for (int i = 0; i < orig.length; i++) {
        assertEquals("Byte at index " + i + " was invalid", orig[i], read[i]);
    }
}


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@commons.apache.org
For additional commands, e-mail: user-help@commons.apache.org


Mime
View raw message