1

In my current spring project, I have a form with some input[type=file] fields which need be handled by this PropertyEditorSupport class:

public class ImagemEditor extends PropertyEditorSupport {
  private String file_path = System.getProperty("user.home")+File.separator+".store"+File.separator+"Pictures";

  @Override
  public void setAsText(String text) {
    ...
  }
  ...
}

the image is sent to server as a Base64 String and it's added to the other params by this javascript code:

  $('input[type=file]').on("change", function(){
    var id = $(this).attr("id");
    var name = $(this).attr("name");
    if(typeof id !== "undefined") {
      if(this.files.length > 0) {
        reader = new FileReader();
        reader.onloadend = function () {
          str += "&" + name + "=" + this.result;
        }
        reader.readAsDataURL(this.files[0]);
      }
    }
  });

In the PropertyEditorSupport class, I read the String with the Base64 encoded image and convert to byte[], just to store this bytes into a file:

  byte[] buffer = Base64.decodeBase64(text.split(",")[1]);

  File arquivo;
  try {
    arquivo = new File(file_path+File.separator+file_name()+".jpeg");
  } catch (Exception e) {
    e.printStackTrace();
    arquivo = null;
  }

  File dir = new File(file_path);
  if(!dir.exists())
    dir.mkdirs();
  if(!arquivo.exists())
    try {
      arquivo.createNewFile();
    } catch (Exception e) {
      e.printStackTrace();
    }

  FileOutputStream fileOut;
  try {
    fileOut = new FileOutputStream(arquivo);
  } catch (Exception e) {
    e.printStackTrace();
    fileOut = null;
  }

  try {
    fileOut.write(buffer);
  } catch (Exception e) {
    e.printStackTrace();
  }

  try {
    fileOut.close();
  } catch (Exception e) {
    e.printStackTrace();
  }

but when I try open the resulting image, it isn't the same image I upload (I use the command line tool vbindiff to verify that, and the header of the image is always the same). It's not even possible open the resulting image (I am using Gwenview on Linux/Kubuntu).

Someone can see what's wrong here?

16
  • The buffer here new ByteArrayInputStream(buffer) is the same as the buffer here byte[] buffer ? Commented Mar 2, 2017 at 20:27
  • yes, it's the same variable. Commented Mar 2, 2017 at 20:48
  • 1
    You can search for javascript base64 encoding and java base64 decoding. Commented Mar 2, 2017 at 21:00
  • 4
    While adding the bounty might help you, I think you could already have had an answer, if you had only bothered to present a problem that is reproducible. Random code and error messages that tells you that the input is corrupted doesn't really help much unless you actually provide the input that caused those errors... Commented Mar 5, 2017 at 10:16
  • 1
    To throw in another option, just use multipart/form-data for file uploading. Commented Mar 10, 2017 at 13:04

1 Answer 1

3
+25

I tried to put up a very short example using just the jre.

You just need to put the html in index.html in the working directory, run the server and upload an example image.

This is just example code, so your app will be running on a servlet container of some kind, you will have to adapt code to the actual request and response object you have.

Index Page

<html>
<head>
<title>Test file</title>
<script type="text/javascript">
    function sendFile() {
        var file = document.querySelector('input[type=file]').files[0];
        var reader = new FileReader();

        reader.addEventListener("load", function() {
            var http = new XMLHttpRequest();
            var url = "save_file";

            http.open("POST", url, true);
            http.setRequestHeader("Content-type",
                    "application/x-www-form-urlencoded");
            http.onreadystatechange = function() {//Call a function when the state changes.
                if (http.readyState == 4 && http.status == 200) {
                    console.info(http.responseText);
                }
            }
            var header = "base64,";
            var pos=reader.result.indexOf(header);
            var data = reader.result.substring(pos+header.length);
            http.send(data);
        }, false);

        if (file) {
            reader.readAsDataURL(file);
        }
    }
</script>
</head>
<body>
    <input type="file" onchange="sendFile()">
    <br>
</body>
</html>

The HTTP Server

package so;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.util.Base64;
import java.util.Scanner;


import com.sun.net.httpserver.*;

public class LoadImage {

    public static void main(String[] args) throws IOException {
         HttpServer server = HttpServer.create(new InetSocketAddress(8000), 0);
         server.createContext("/save_file",FileSaveHandler());
         server.createContext("/", indexHandler());
         server.start();
         System.out.println("Server started");
         Scanner scanner = new Scanner(System.in);
         scanner.nextLine();
         System.out.println("Server stopped");
         server.stop(0);
    }

    private static HttpHandler indexHandler() {
        return new HttpHandler() {
            @Override
            public void handle(HttpExchange exchange) throws IOException {
                File f = new File("index.html");
                try(OutputStream responseBody = exchange.getResponseBody();InputStream in =  new FileInputStream(f);){
                    byte[] buffer = new byte[(int)f.length()];
                    in.read(buffer);
                    exchange.sendResponseHeaders(200, buffer.length);
                    responseBody.write(buffer);
                }
            }
        };
    }

    private static HttpHandler FileSaveHandler() {
        return new HttpHandler() {

            @Override
            public void handle(HttpExchange exchange) throws IOException {

                try(InputStream in = exchange.getRequestBody();
                    OutputStream out = new FileOutputStream("out.jpg")){

                    byte [] buffer = new byte[3*1024];
                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
                    int l = 0;
                    while((l=in.read(buffer))>=0){
                        bos.write(buffer, 0, l);
                    }
                    byte[] data = Base64.getDecoder().decode(bos.toByteArray());
                    out.write(data);
                }

            }
        };
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.