0

So I am using following Rest method in my web application to upload files. When I upload Text files, they are saved properly and i can open them. But in case of any other format i.e. *.docx or *.pdf or *.jpg, the files are stored with exact size as original files but are corrupted. Following is the code:

@POST
@Consumes("multipart/form-data")
public Response readFile() throws IOException, ServletException {
    Part filePart = request.getPart("c");
    InputStream f = filePart.getInputStream();
    String l = null;
    DataInputStream ds = new DataInputStream(f);
    File file = new File("c:\\temp\\" + getSubmittedFileName(filePart));
    try {
        BufferedWriter bw = new BufferedWriter(new FileWriter(file));
        while ((l = ds.readLine()) != null) {
            bw.write(l);
        }
        bw.flush();
        bw.close();
        return Response.status(201).entity("File Created").build();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return Response.status(500).build();
}

and the html page as follows:

<form action="api/fetch" method="post" enctype="multipart/form-data">
        <input id="c" name="c" type="file" aria-required="true"><br/><br/>
        <button type="submit">Submit</button>
</form>

I assume there must be another way to upload files rather than this. i have refereed to How to upload files to server using JSP/Servlet? but i assume it doesn't say anything about handling file extension. So, what is going wrong with my code?

Community
  • 1
  • 1
BingAring
  • 117
  • 1
  • 1
  • 10

1 Answers1

3

I believe the error is here

DataInputStream ds = new DataInputStream(f);
...
while ((l = ds.readLine()) != null) {

From DataInputStream.readLine Javadoc

This method does not properly convert bytes to characters.

You should use a FileInputStream instead of a DataInputStream. The FileInputStream treat all your files as bytes. Beside the mentioned problem readLine would also strip during reading all linebreaks from your input file.

edit For demonstration see below small snippet.

The file dummy.txt contains

foo
bar

The linebreak after foo is a single \n. In a hex dump it is

66 6F 6F 0A 62 61 72

Now the file is read once using a DataInputStream and once with a FileInputStream

try (DataInputStream ds = new DataInputStream(new FileInputStream("dummy.txt"));
        Writer bw = new BufferedWriter(new FileWriter("out_writer.txt"))) {
    String l;
    while ((l = ds.readLine()) != null) {
        bw.write(l);
    }
}
try (InputStream in = new FileInputStream("dummy.txt");
        OutputStream out = new FileOutputStream("out_inputstream.txt")) {
    byte[] buffer = new byte[8192];
    int readBytes = -1;
    while ((readBytes = in.read(buffer)) > -1) {
        out.write(buffer, 0, readBytes);
    }
}

The output files are

out_writer.txt

ASCII: foobar
hex  : 66 6F 6F 62 61 72

out_inputstream.txt

ASCII: foo
       bar
hex  : 66 6F 6F 0A 62 61 72

As you can see the 0A (the \n) is stripped in the DataInputStream example. And this stipped line break garbles your output files.

SubOptimal
  • 22,518
  • 3
  • 53
  • 69