Reputation: 303
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
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
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