Play Framework - Ajax web service call image request issue - java

I have developed web service using Play framework. I have created POST rest service in Play framework as below.
In routes file:
POST /imageUpload controllers.Application.imageUpload()
In Application.java:
public static Result imageUpload() {
ObjectNode result = Json.newObject();
MultipartFormData body = request().body().asMultipartFormData();
FilePart file = body.getFile("file");
File trainImg = file.getFile();
File temp = new File("/Play_Framework/temp.jpg");
trainImg.renameTo(temp);// moved the image to another folder to check the correct image.
.
.
.
return ok(result);
}
In the service, I have written the code to save the image which is received from the request.
I have called this service from the Ajax as given below.
In my index.html file:
var formData = new FormData();
var blob = new Blob([imageData], { type: "image/jpg"});
formData.append("file", blob, "capturedImage.jpg");
$.ajax({
url: 'http://localhost:9000/imageUpload',
data: formData,
crossDomain: true,
processData: false,
contentType: false,
async: false,
cache: false,
dataType: "json",
type: 'POST',
success: function(data){
alert(data);
var responseStr = JSON.stringify(data);
alert("Response str -- "+responseStr);
}
});
When I upload the file as Multipart form data, I can receive it as multipart data in the server side. But it is stored as "multipartBody7906599875117091855asTemporaryFile".
If I get this file's mimitype - "content/unknown".
When I debug, I got the below multipart form data path "/var/folders/f3/r3rfqfl949z5pf2cprwn95dm0000gn/T/multipartBody7906599875117091855asTemporaryFile".
How do parse this as "jpg" file? Can anyone help me to do this?

The following worked for me:
Application.java
public class Application extends Controller {
public static Result index() {
return ok(index.render("SO answer 30229421"));
}
public static Result imageUpload() {
ObjectNode result = Json.newObject();
Http.MultipartFormData body = request().body().asMultipartFormData();
Http.MultipartFormData.FilePart file = body.getFile("file");
File trainImg = file.getFile();
File temp = new File("/tmp/temp.jpg");
trainImg.renameTo(temp); // moved the image to another folder to check the correct image.
result.put("path", temp.getAbsolutePath());
return ok(result);
}
public static Result imageDownload(String path) {
return ok(new File(path));
}
index.scala.html
#(message: String)
<html>
<body>
<h1>#message</h1>
<input type="file" id="imageData"/>
<button onclick="send()">Send image</button>
<div id="image">
</div>
<script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<script>
function send() {
var imageData = $('#imageData')[0].files[0];
var formData = new FormData();
var blob = new Blob([imageData], { type: "image/jpg"});
formData.append("file", blob, "capturedImage.jpg");
$.ajax({
url: 'http://localhost:9000/imageUpload',
data: formData,
crossDomain: true,
processData: false,
contentType: false,
async: false,
cache: false,
dataType: "json",
type: 'POST',
success: function(data){
$('#image').html('<img src="http://localhost:9000/imageDownload?path=' + data.path + '"/>');
}
});
}
</script>
</body>
</html>
The only difference, is that because you didn't include how you get the imageData value, I used this version (as per this SO answer):
var imageData = $('#imageData')[0].files[0];

Related

Multiple files upload using AngularJS and Spring Boot

I am trying to upload multiple files at a time using Spring Boot and AngularJS.
Spring Boot file
#RequestMapping(value = "/fileUpload", method = RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE )
public #ResponseBody boolean UploadFile(#RequestParam(value = "file", required = true) MultipartFile[] files){
Here I am getting the value of MultipartFile[] files as MultipartFile[0]#17615 instead of an array of MultipartFiles. The length of the array is 0.
HTML File
<input type="file" file-model="myFile" name="filePath" ng-model="filePath" on-click="false" multiple required>
AngularJS file
app.directive('fileModel', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var model = $parse(attrs.fileModel);
var modelSetter = model.assign;
element.bind('change', function(){
scope.$apply(function(){
modelSetter(scope, element[0].files);
});
});
}
};
}]);
app.service('fileUpload', ['$http', 'growl', '$state', function ($http, growl, $state) {
this.uploadFileToUrl = function(file, uploadUrl){
var fd = new FormData();
for(let i=0;i<file.length;i++){
fd.append('file', file[i]);
}
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.success(function(data, status, headers) {
.....
})
.error(function(error){
.....
});
}
}]);
app.controller('uploadauditfilectrl', ['$scope', 'fileUpload', '$cookieStore', function($scope, fileUpload, $cookieStore){
$scope.uploadFile = function(){
var file = this.myFile;
var uploadUrl = "/fileUpload/";
fileUpload.uploadFileToUrl(file, uploadUrl);
};
}]);
Can anyone please tell me the mistake I am doing.

How to implement multiple files upload with extra fields per each file in Spring Boot

How to implement multiple file upload feature, with each of file have it own extra field (eg. comment, documentType) in Spring Boot?
This answer might be related but it's for single file only:
Spring boot controller - Upload Multipart and JSON to DTO
Html side
<input id="files" type="file" name="files[]" multiple />
Upload
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.min.js" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
<script type="text/javascript">
function uploadFiles(){
var form = new FormData();
var i=0;
$.each($("input[type='file']")[0].files, function(i, file) {
form.append('file', file);
form.append('extradata','ola'+i);
i++;
});
// send form data with ajax
$.ajax({
type: 'POST',
url: '/uploadFiles',
cache: false,
contentType: false,
processData: false,
data : form,
success: function(result){
console.log(result);
alert('upload success');
},
error: function(err){
console.log(err);
}
})
}
</script>
and server side
#PostMapping("/uploadFiles")
public String uploadFiles(#RequestParam("file") MultipartFile[] files,
#RequestParam("extradata") String[] extras) throws Exception {
int i = 0;
Files.createDirectories(Paths.get("./uploaded/"));
for (MultipartFile f : files) {
Files.copy(f.getInputStream(), Paths.get("./uploaded/" + extras[i] + f.getOriginalFilename()));
i++;
}
return "success";
}
you can find running example here https://github.com/ozkanpakdil/spring-examples/tree/master/demoMultiFileUpload
You can encode multiple request parts in the POST payload and process that with Spring Boot.
Let's say you need to pass in two things per file:
Blob with the file contents
metadata - an object that can hold whatever - title/comments - you name it.
FrontEnd
You can use anything to simulate FormData params, this is in TypeScript:
let's say a document looks like this:
export interface NewDocument {
title: string,
comment: string,
author: string,
file: File
}
So the generating of the FormData might be like:
private getFormData(doc: NewDocument): FormData {
let formData: FormData = new FormData();
const json: Blob = new Blob([JSON.stringify(doc)], {type: 'application/json'});
formData.append('metadata', json); //adding the metadata
const blob: Blob = new Blob([doc.file[0]], {type: doc.file[0].type});
formData.append('file', blob); //adding the file contents
return formData;
}
You can then POST the form data to a given endpoint.
BackEnd
You can specify the different RequestParts you're expecting in the request
#PostMapping
public ResponseEntity<Void> uploadFile(#RequestPart("metadata") FileMetadata metadata,
#RequestPart("file") MultipartFile file) {
//process
}
FileMetadata here is a custom Java POJO into which you can deserialize the JSON representation of the FrontEnd's NewDocument
You should be able to turn this into a multiples version.
#PostMapping
public ResponseEntity<Void> uploadFile(#RequestPart("metadata") FileMetadata[] metadatas,
#RequestPart("file") MultipartFile[] files) {
//process
}
The problem now is how to identify which metadata is for which file.
A simple way would be to have the filename encoded in the metadata object and use that for mapping.

JAVA: Upload Multipart file

I am struggling with Multipart file upload in Spring controller. I've read multiple questions, googles, but nothing seems to work.
I get
error: "Bad Request"
exception: "org.springframework.web.multipart.support.MissingServletRequestPartException"
message: "Required request part 'file' is not present"
My BE controller:
#RequestMapping(value = "/zip", method = RequestMethod.POST)
public void readFile(#RequestParam("file") MultipartFile file) throws IOException {
// code
}
FE, angularJS:
service.getZip = function getZip(file) {
var formData = new FormData();
formData.append('file', file);
return $http({
method: 'POST',
url: CONSTANTS.readFile,
data: formData,
headers: {'Content-Type': undefined}
}) .then(function (response) {
var data = response.data;
return data.id;
});
}
HTML:
<input type="file" id="file" name="file" accept=".txt"/>
also application.properties contain:
spring.http.multipart.enabled=false
UPDATE:
I no longer get that error when following #Byeon0gam advice to remove #RequestParam from my controller, but the my file is null as it comes to controller. Although in FE service, as I see, it's not empty:
change the Content-Type in your FE to:
headers: {'Content-Type': 'x-www-form-urlencoded'}
hope it will work for you.

RequestParam annotation doesn't work with POST

I have the following controller:
#RequestMapping(value = { "/member/uploadExternalImage",
"/member/uploadExternalImage" }, method = RequestMethod.POST)
public String handleFileUpload(#RequestParam("url") String url,
Principal principal) throws IOException {
File file = restTemplate.getForObject("url", File.class);
file.toString();
return null;
}
And I have the following ajax:
$.ajax({
url: 'uploadExternalImage', //Server script to process data
type: 'POST',
success: function () {
},
complete:function(){
$.fancybox.hideLoading();
},
// Form data
data: {url: files[0].link},
cache: false,
contentType: false,
processData: false
});
in spring log I see that
org.springframework.web.bind.MissingServletRequestParameterException: Required String parameter 'url' is not present
if I change ajax method with GET:
$.ajax({
url: 'uploadExternalImage?url=123', //Server script to process data
type: 'POST',
success: function () {
},
complete:function(){
$.fancybox.hideLoading();
},
error: function (data) {
},
cache: false,
contentType: false,
processData: false
});
it works fine
How does to configure spring correctly?
Http POST is capable of being used for request parameters on request body. But you are trying to use it on a different way.
Try this:
$.ajax({
type: 'POST',
url: "uploadExternalImage?url=BLABLA",
data: text,
success: function (data) {
//
}
});
If you want it on request body then use #RequestBody

Java Ajax request parameters have null value

I'm trying to make a simple ajax request using Java (JSP + Servlet) and Ajax (jQuery). The Ajax request is working as expected, and the servlet code is reached.
The problem is that I can't get the values of the parameters sent by the request. I get null values.
This is the code in the servlet:
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("application/json");
String perfilId = request.getParameter("perfilId"); //Null value
String perfilNombre = request.getParameter("perfilNombre"); //Null value
try (PrintWriter out = response.getWriter()) {
Gson gson = new Gson();
JsonObject obj = new JsonObject();
obj.addProperty("mensaje", "AlgĂșn mensaje. Id: " + perfilId + ", Nombre: " + perfilNombre);
out.print(gson.toJson(obj));
out.flush();
}
}
Ajax request inside a JSP:
$.ajax({
type: "POST",
url: 'srvl_def',
cache: false,
contentType: "application/json;",
dataType: "json",
data: {
perfilId: $('#perfilId').val(),
perfilNombre: $('#perfilNombre').val()
},
success: function (data) {
alert(data.mensaje);
}
});
The request data looks like this:
perfilId=1&perfilNombre=nuevo
Perhaps I'm missing something?
EDIT
This is the HTML
<input type="text" id="perfilId" />
<input type="text" id="perfilNombre" />
<button type="button" id="btnGuardar">Enviar</button>
<script src="js/jquery.js" type="text/javascript"></script>
<script type="text/javascript">
$('#btnGuardar').click(function (){
//ajax call
});
</script>
Following this answer, #ShaunakD referenced this in a comment (see question), I was able to obtain the values sent by the ajax call.
The call looks like this:
var perfilId = $('#perfilId').val();
var perfilNombre = $('#perfilNombre').val();
$.ajax({
type: "POST",
url: 'srvl_def',
cache: false,
contentType: "application/x-www-form-urlencoded; charset=UTF-8;",
dataType: "json",
data: {
perfilId: perfilId,
perfilNombre: perfilNombre
},
success: function (data) {
alert(data.mensaje);
}
});
if your ajax call is inside some function try this :
var perfilId = $('#perfilId').val();
var perfilNombre = $('#perfilNombre').val();
$.ajax({
type: "POST",
url: 'srvl_def',
cache: false,
contentType: "application/json;",
dataType: "json",
data: {
perfilId: perfilId ,
perfilNombre: perfilNombre
},
success: function (data) {
alert(data.mensaje);
}
});

Categories

Resources