How to upload image using REST in angular? - angularjs

<input id="uploadImageId" type="file" accept="image/*" onChange="angular.element(this).scope().uploadPic(this);">
Controller:
$scope.uploadPic = function(input) {
if (input.files && input.files[0]) {
ContactService.uploadContactImage.upload({
fileName : input.files[0].name
}, input.files[0], function(data) {
});
}
}
};
Service:
uploadContactImage : $resource('/services/api/contacts/uploadContactImage/:fileName',
{
fileName : '#fileName'
}, {
upload : {
method : 'POST',
headers: {'Content-Type': 'multipart/form-data; boundary='}
}
})
API:
#POST
#Path("/uploadContactImage/{fileName}")
#Produces("application/json")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Map<String, Object> uploadContactImage(
#PathParam("fileName") String fileName,
#FormDataParam("file") InputStream uploadedInputStream,
#FormDataParam("file") FormDataContentDisposition contentDispositionHeader,
#Context HttpServletRequest httpServletRequest) throws GaException {
BufferedImage image = ImageIO.read(uploadedInputStream);
ImageIO.write(image, "jpg", new File("/../../fileName));
}
Output:
java.lang.IllegalArgumentException: image == null!
at javax.imageio.ImageTypeSpecifier.createFromRenderedImage(ImageTypeSpecifier.java:925)
at javax.imageio.ImageIO.getWriter(ImageIO.java:1591)
at javax.imageio.ImageIO.write(ImageIO.java:1520)
Please guide me in this
Did I miss any param's to be passed in header? Or how can I pass #FormDataParam in angularjs?

The solution for me was to include mimepull-1.9.4.jar. http://mvnrepository.com/artifact/org.jvnet.mimepull/mimepull/1.9.4

Related

View pdf from spring get request via react/axios

I have a spring endpoint that serves a pdf as a byte[] and a React ui that is getting a 406 when I try to call the endpoint.
spring endpoint:
#GetMapping(value = "report/{report_id}", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<InputStreamResource> generateReviewTaskReport(
HttpServletResponse response,
#PathVariable("report_id") String reportId,
#RequestAttribute(USER_ID) String loginId) {
byte[] report = reportService.generateReport(reportId, loginId);
ByteArrayInputStream inputStream = new ByteArrayInputStream(report);
HttpHeaders headers = new HttpHeaders();
headers.setContentLength(report.length);
headers.add("Content-Disposition", "inline;filename=" + reportId + "_report.pdf");
return ResponseEntity
.ok()
.headers(headers)
.contentType(MediaType.APPLICATION_PDF)
.body(new InputStreamResource(inputStream));
}
I've tried:
headers.add("Content-Disposition", "attachment;filename=" + reportId + "_report.pdf");
same result.
react request:
export const getReport = (reportId = '') => (dispatch) => {
const report = `${apiConfig.reportUrl}${reportId}`
const promise = axios.get(report,
{
responseType: 'blob',
headers: {
'Accept': 'application/pdf'
}
})
return dispatch({
type: GET_REPORT,
payload: promise,
})
}
case GET_REPORT:
if (payload.data) {
const report = new Blob([payload.data])
reportUrl = URL.createObjectURL(report)
window.open(reportUrl, "_blank")
}
I've tried responseType: 'bufferArray', returning a plain byte[] from my spring endpoint, always get a 406. I'm guessing it's because I have the wrong mime type in my 'Accept' header. I've tried 'application/pdf' and '*/*', same result. What headers do I need to accept an InputStreamResource or byte[]?
With postman I can download the file just fine.
my config:
#Component
public class WebConfiguration extends WebMvcConfigurationSupport {
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(byteArrayHttpMessageConverter());
converters.add(new ResourceHttpMessageConverter());
}
#Bean
public HttpMessageConverter byteArrayHttpMessageConverter() {
ByteArrayHttpMessageConverter arrayHttpMessageConverter =
new ByteArrayHttpMessageConverter();
arrayHttpMessageConverter.setSupportedMediaTypes(getSupportedMediaTypes());
return arrayHttpMessageConverter;
}
private List<MediaType> getSupportedMediaTypes() {
List<MediaType> mediaTypes = new ArrayList<>();
mediaTypes.add(MediaType.APPLICATION_PDF);
mediaTypes.add(MediaType.APPLICATION_OCTET_STREAM);
return mediaTypes;
}
}
A general solution, but i think in you'r case it should works fine ;)
axios({
url: 'http://api.dev/file-download', //your url
method: 'GET',
responseType: 'blob', // important
}).then((response) => {
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', 'file.pdf'); //or any other extension
document.body.appendChild(link);
link.click();
});
gist: https://gist.github.com/javilobo8/097c30a233786be52070986d8cdb1743
Full credits to: https://gist.github.com/javilobo8

Angularjs $http get not working

I am trying to access REST web service from angularjs. I am not able to call it successfully.
AngularJs Code
var singleOrderUrl = "/singleOrder/retrieve";
function getSingleOrderDetails(userName,singleOrderUrl,$http,$q) {
var fd = new FormData();
var deffered = $q.defer();
fd.append('USERNAME', 'test123');
//fd.append();
//fd.append();
console.log("inside service"+userName+"singleOrderUrl:::"+singleOrderUrl);
return $http.get(singleOrderUrl, fd, {
withCredentials : false,
transformRequest : angular.identity,
headers : {
'Content-Type' : undefined,
}
}).success(function(response) {
console.log(response);
responseData = response.data.toString();;
deffered.resolve(response);
return responseData;
}).error(function(error) {
alert("error");
deffered.reject(error);
return "failed";
});
};
Rest Service code
#RestController
public class SingleOrderHistoryController {
private static final Logger logger = LoggerFactory.getLogger(SingleOrderHistoryController.class.getName());
#RequestMapping(value = "/singleOrder/retrieve", method=RequestMethod.GET, produces="application/json")
public List<SingleHistoryRecord> getSingleOrderDetails(#RequestParam(value = Constants.USER_NAME, required = true) String userName, HttpServletRequest request,HttpServletResponse response) throws Exception {
logger.debug("inside SingleOrderHistoryController ");
List<SingleHistoryRecord> singleOrderHistoryList = new ArrayList<SingleHistoryRecord>();
SingleHistoryRecord record1 = new SingleHistoryRecord();
SingleHistoryRecord record2 = new SingleHistoryRecord();
record1.setClientIdentifier(userName);
record1.setSubmitDate("01/05/2017");
record1.setStatus("Complete");
record1.setReferenceID("1234555");
record1.setOrderID("test123");
record2.setClientIdentifier(userName);
record2.setSubmitDate("01/05/2017");
record2.setStatus("Complete");
record2.setReferenceID("1234555");
record2.setOrderID("test123");
singleOrderHistoryList.add(record1);
singleOrderHistoryList.add(record2);
return singleOrderHistoryList;
}
Can anyone please advise what I am doing wrong here, It is getting the source code of the page in response instead of getting the list.

How to pass class object in angularjs function

I have a class
public class Customer
{
private int _Id;
public int Id
{
get { return _Id; }
set { _Id = value; }
}
private String _Name;
public String Name
{
get { return _Name; }
set { _Name = value; }
}
private String _Address;
public String Address
{
get { return _Address; }
set { _Address = value; }
}
}
I need to save data using this class. I need to know how to call this class in data function
$scope.Save = function () {
var httpreq = {
method: 'POST',
url: 'ajs.aspx/Save',
headers: {
'Content-Type': 'application/json; charset=utf-8',
'dataType': 'json'
},
data: { //** Here How to call assign object value for my customer class **// }
}
$http(httpreq).success(function (response) {
alert("Saved successfully.");
})
};
How to create class object and assign value for my customer class in this data section.
In my web method
[System.Web.Services.WebMethod()]
public static void Save(Customer objcsr)
{
using (SqlConnection con = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["DBConnection"].ConnectionString))
{
using (SqlCommand cmd = new SqlCommand())
{
cmd.Connection = con;
cmd.CommandText = "insert into customer (Name, Address) values (#Name, #Address);";
cmd.Parameters.AddWithValue("#Name", objcsr.Name);
cmd.Parameters.AddWithValue("#Address", objcsr.Address);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
}
}
You need pass the json format data with the class properties, Try this below code
Var objcsr={Id:"1",Name:"Donald Trump",Address:"Alien Planet"}
$scope.Save = function () {
var httpreq = {
method: 'POST',
url: 'ajs.aspx/Save',
headers: {
'Content-Type': 'application/json; charset=utf-8',
'dataType': 'json'
},
data: objcsr
}
$http(httpreq).success(function (response) {
alert("Saved successfully.");
})
};
When you are sending data from client to server, according to the best practices, the data should be sent either in the form of XML or JSON.
Hence, the JSON of your class object could be something like
var obj = {
"id" : "YOUR ID",
"name" : "YOUR NAME",
"address" : "YOUR ADDRESS"
}
Moreover, according to the best practices, the http requests should be made using a factory or service.
So your factory should be something like
angular.module("YOUR_MODULE").factory('YOUR_SERVICE',function($http,$q){
var obj = {};
obj.saveObject = function(data){
var defer = $q.defer();
$http.post("YOUR URL",data).then(function(response){
defer.resolve(response);
},function(error){
defer.reject(error);
});
return defer.promise;
}
return obj;
});
And thus you can make a controller call as
$scope.Save = function (data) {
YOUR_SERVICE.saveObject(data);
}
and that can be called like
var obj = {
"id" : "YOUR ID",
"name" : "YOUR NAME",
"address" : "YOUR ADDRESS"
}
$scope.Save(obj);
If your getting it from form elements then you should be using it like
$scope.Save = function () {
var customerObject={
"Id": $scope.customerId,
"Name": $scope.customerName,
"Address":$scope.customerAddress
};
var httpreq = {
method: 'POST',
url: 'ajs.aspx/Save',
headers: {
'Content-Type': 'application/json; charset=utf-8',
},
data: { customerObject }
}
$http(httpreq).success(function (response) {
alert("Saved successfully.");
})
};
Also Note that, the objectName and their respective properties that your are passing should match with that of the objectName in webmethod. For example
Your properties are
your corresponding json object must have the same properties
Id: $scope.Id
Name: $scope.Name
Address: $scope.Address

The current request is not a multipart request in angularJS and Spring Rest

I am trying to upload file using AngularJS on client side and Spring RESTApi on server side but getting
Error
org.springframework.web.multipart.MultipartException: The current request is not a multipart request
at org.springframework.web.method.annotation.RequestParamMethodArgumentResolver.assertIsMultipartRequest(RequestParamMethodArgumentResolver.java:216)
at org.springframework.web.method.annotation.RequestParamMethodArgumentResolver.resolveName(RequestParamMethodArgumentResolver.java:167)
.......
[http-bio-8080-exec-1] WARN org.springframework.web.servlet.PageNotFound - Request method 'POST' not supported
Rest API
Below is a simple Java Post function:
#RequestMapping(method = RequestMethod.POST)
public String saveFile(
#RequestParam("file") MultipartFile file) {
return "success";
}
In Angular, I am using Resource service to send request.
Chrome Developer Tool output
Request Payload
------WebKitFormBoundarydFRgXclyfPVixdHo
Content-Disposition: form-data; name="file"; filename="Release_Notes.txt"
Content-Type: text/plain
------WebKitFormBoundarydFRgXclyfPVixdHo--
Angular Service
function FileUploadService($resource) {
return $resource('/fileUpload/:id', {}, {
'save' : {
method : 'POST',
transformRequest: function(data, headersGetter) {
var headers = headersGetter();
headers['Content-Type'] = undefined;
if (data == undefined) {
return data;
}
var fd = new FormData();
var createKey = function(_keys_, currentKey) {
var keys = angular.copy(_keys_);
keys.push(currentKey);
var formKey = keys.shift()
if (keys.length) {
formKey += "[" + keys.join("][") + "]"
}
return formKey;
};
var addToFd = function(object, keys) {
angular.forEach(object, function(value, key) {
var formKey = createKey(keys, key);
if (value instanceof File) {
fd.append(formKey, value);
} else if (value instanceof FileList) {
if (value.length == 1) {
fd.append(formKey, value[0]);
} else {
angular.forEach(value, function(file, index) {
fd.append(formKey + '[' + index + ']', file);
});
}
} else if (value && (typeof value == 'object' || typeof value == 'array')) {
var _keys = angular.copy(keys);
_keys.push(key)
addToFd(value, _keys);
} else {
fd.append(formKey, value);
}
});
};
addToFd(data, []);
return fd;
}
}
});
}
Any hint to avoid this error?
Method assertIsMultipartRequest from RequestParamMethodArgumentResolver class is called.
The method asserts that it is a post request and content type starts with multipart/
if (!"post".equals(request.getMethod().toLowerCase())) {
return false;
}
String contentType = request.getContentType();
return (contentType != null && contentType.toLowerCase().startsWith("multipart/"));
Your content type, on the other hand, is
Content-Type: text/plain
And an exception is thrown.
#RequestMapping(method = RequestMethod.POST)
your value attribute is missing in the requestmapping it should be like this
#RequestMapping(value="/fileupload/save/{id}" ,method = RequestMethod.POST)
and use this code when creating angular resource
$resource('fileupload/save/:id',
{id:'1'}, {
save: {method:'POST', params:{charge:true}}
});
in springBoot theres not much to configure when uploading the file.
but you can add these properties to your application property file to change the file size limits.
# File size limit
multipart.maxFileSize = 3Mb
# Total request size for a multipart/form-data
multipart.maxRequestSize = 20Mb
The above issue is resolved by:
1) Creating a MultipartResolver bean in WebAppConfig.java as shown below:
#Bean
public MultipartResolver multipartResolver() {
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
return multipartResolver;
}
2) Replacing AngularJS FileUploadService (which is using Resource service) with http as shown below:
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
});
Hope it helps.

415- Unsupported Media Type Error | angularjs + Spring3.2

I am getting 415 error in browser. I am not able to find the mistake. Could you please help.
loginController.js
$scope.user = {email: "admin", password: "password"};
$http.post('/expense-manager-api/login/authenticate', $scope.user, {
headers: {"Content-Type": "application/json"}
}).success(function(login) {
$scope.setError(login.status);
$location.path("main");
}).error(function() {
$scope.setError('Invalid user/password combination');
});
LoginController.java
#Controller
#RequestMapping("/login")
public class LoginController {
#RequestMapping(value = "/authenticate", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public
#ResponseBody
LoginResponse login(#RequestBody LoginRequest loginRequest) {
if (loginRequest.getEmail().equals("admin") && loginRequest.getPassword().equals("password")) {
UUID uuid = UUID.randomUUID();
return new LoginResponse(uuid.toString(), "OK");
}
return new LoginResponse(null, "Invalid user/password combination");
}
}
Jackson mapper fixed the problem.
add maven dependency of Jackson-mapper in your pom.xml

Resources