Nuno Neto
Nuno Neto

Reputation: 303

Send ZIP file to server in Base64 via POST

I'm trying to send a zip containing multiple files from the client side to the server using an ajax request. The zip is encoded into a Base64 String in javascript and passed as a post parameter

Javascript code:

            var fileUp = document.getElementById("wsFile");
            var file = fileUp.files[0];

            var array = new Array();
            array = file.name.split(".");


            var reader = new FileReader();
            reader.readAsDataURL(file);

            if(array[array.length-1]=="zip" && file.size<=10000000){

                var xhr = new XMLHttpRequest();
                xhr.open("POST", "X",true);
                xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");


                 xhr.onreadystatechange = function() {
                     if(xhr.readyState == 4 && xhr.status == 200) {
                         dojo.byId("content").innerHTML=xhr.responseText;
                     }
                 }
                 reader.onload = function(){
                     var params = "file="+ reader.result+"&fileName="+file.name;
                     xhr.send(params);
                };

}

Server-side(Spring MVC):

@RequestMapping(value = "/X", method = RequestMethod.POST)
    public String X(@RequestParam("file") String file, @RequestParam("fileName") String fileName, Locale locale, Model model) {


            System.out.println(file);

            byte[] decoded = Base64.decodeBase64(file);

            System.out.println(decoded);


            File folder = new File("C:\\MTT");
            if(!folder.exists()){
                folder.mkdir();
            }

            File f = new File("C:\\MTT\\"+fileName);



try {
                    FileOutputStream fos = new FileOutputStream(f);
                    fos.write(decoded);
                    fos.close();
                } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }   

So far so good, the ajax request is successful and the server receives the same Base64 String that the client sent. However, when I try to extract the files inside the zip, I get a corrupt archive message.

Am I doing something wrong or is this a limitation of zip archives? Sorry for any naiveness, but I've never done this before

Upvotes: 1

Views: 7159

Answers (2)

Paul S.
Paul S.

Reputation: 66304

Looking through your code, I believe you're not sending what you think you're sending!

It's due to these two lines

reader.readAsDataURL(file);
// and later
var params = "file="+ reader.result+"&fileName="+file.name;

Consider; what does readAsDataURL actually produce? e.g.

var b = new Blob(['Hello World!'], {type: 'text/plain'}),
    fr = new FileReader();
fr.onload = function () {console.log(this.result);};
fr.readAsDataURL(b);
// data:text/plain;base64,SGVsbG8gV29ybGQh

i.e. your reader.result is not just Base64 data, so not exactly what you want

var base64Data = reader.result.slice(reader.result.indexOf(',') + 1);
var params = "file=" + base64Data + "&fileName=" + file.name;

Note that the Base64 in my example is longer than the text it represents. This will always be true, so you might want to consider sending the file as a binary instead; just pass file directly into send with content type e.g. application/octet-stream, though this will also mean your server code would need to be changed too, for how it reacts.

Upvotes: 2

Juned Ahsan
Juned Ahsan

Reputation: 68715

I believe for sending the zip file , OCTET stream should be used as content-type. Another problem in your code is that you are just taking the file name as the input. But to receive a file you should have the inputstream for the file. Also you should send the file contents and not just the name of the file.

If you need to send multiple form params with you request such as file metadata and actual file contents, then using Multipart/form or Multipart/mixed content types should be considered.

Here is a good tutorial for sending files using jersey framework. No matter what framework you are using, but you can take the learnings from the example:

http://www.mkyong.com/webservices/jax-rs/file-upload-example-in-jersey/

Upvotes: 0

Related Questions