I've been fighting for days with this problem:insert file into database with Spring Boot, JPA Hibernate and Vue.js frontend. (Yes I know it's better to store the location to retrieve the file and not the file itself, but I have to store the file, so move on.) I tried different solutions but I didn't manage. First I passed the file path from fontend to backend as a normal field of my json data and used:
String path= json.get("file_name").asText();
File file = new File(path);
byte[] fileInBytes = new byte[(int) file.length()];
FileInputStream fileInputStream = new FileInputStream(file);
fileInputStream.read(fileInBytes);
fileInputStream.close();
c.setFile(fileInBytes);
It worked only if I passed the explicit path, because from my HTML input type=file I always got C:/fakepath/filename
and the backend didn't find the file obviously. Is there any way to pass the explicit path? I've searched for a while but I couldn't find a solution, so I changed my mind.
Now I'm passing the base64 encode of the file from the frontend in Vue with this code (thanks to How to convert file to base64 in JavaScript?):
getBase64(file, onLoadCallback) {
return new Promise(function(resolve, reject) {
var reader = new FileReader();
reader.onload = function() { resolve(reader.result); };
reader.onerror = function(error) {
console.log('Error when converting file to base64: ', error);
};
reader.readAsDataURL(file);
});
},
uploadFile: function(event) {
this.input_file = document.getElementById("challenge_file").files[0];
this.base64_file = this.getBase64(this.input_file);
this.base64_file.then(function(result) {
console.log(result);
this.File=JSON.stringify({'file': this.base64_file});
axios.post("/uploadfile",
this.File,
{ headers: {
'Content-type': 'application/json',
}
}).then(function(response){
location.reload(true);
}).catch(function (error){
console.log(error);
});
});
}
this code works and I get a base64 string also in the backend, in which I try to convert it in bytes[] because my file is a @Lob private byte[] file;
. This is my code in the backend controller:
System.out.println(json.get("file"));
//print "data:text/plain;base64,aVZCT1J..."
int init= json.get("file").asText().lastIndexOf(",");
String base64file=json.get("file").asText().substring(init+1);
//I get only the part after 'base64,' *(see below)
System.out.println(base64file);
byte[] decodedByte = Base64.getDecoder().decode(base64file);
//I decode it into bytes[]
c.setFile(decodedByte);
*I get only the the part after 'base64,' otherwise if I use all the String I get this error: enter java.lang.IllegalArgumentException: Illegal base64 character 3a
This code has no errors, but the Blob in the database is empty, while in the first way I could open the file preview from Hibernate, but only if I wrote the correct real path, not retrieving it from the input. Any suggestion? What should I do?
SOLVED: Thanks to an answer to this question I changed my backend into:
System.out.println(json.get("file"));
String data= json.get("file").asText();
String partSeparator = ",";
if (data.contains(partSeparator)) {
String encodedImg = data.split(partSeparator)[1];
byte[] decodedImg = Base64.getDecoder().decode(encodedImg.getBytes(StandardCharsets.UTF_8));
c.setFile(decodedImg);
}
and now I see the correct file in the db.