I need to send JSON to a web service using HTTP POST method in AngularJS to download a file.
AngularJS:-
$http
.post(
'url',
'My Json data ')
.success(function(response) {
console.log('file downloading');
})
.error(
function(response) {
console
.log('Error while downloading file');
});
Spring Controller:-
#RequestMapping(value = "/url", method = RequestMethod.POST)
#ResponseBody
public void getfile(#RequestBody List<ABC> abc, HttpServletResponse response)
throws JRException, IOException, SQLException {
//My code here
response.reset();
response.setContentType("application/x-pdf");
response.setHeader("Content-disposition", "attachment; filename=ABC.pdf");
final OutputStream outStream = response.getOutputStream();
JasperExportManager.exportReportToPdfStream(jasperPrint,outStream);
outStream.flush();
outStream.close();
I have to call this from angular using POST request. How to acheive so?
EDIT
I was able to meet the requirements by referring this thread.
please see this very helpful function to download a file using POST request. Function is dependant on jQuery . the implementation creates a html form inline with hidden field and then submit it
Related
I am trying to send a csv file to my java spring boot backend. The code to send my file is below:
var url = 'http://localhost:3001/UploadFile';
var file = this.state.file;
var formData = new FormData();
formData.append("file", file);
axios.post(url, formData, {
headers: { 'Content-Type': 'multipart/form-data' }
});
And the code to accept my file from Spring Boot:
#CrossOrigin
#RequestMapping("/UploadFile")
#ResponseBody
public void uploadFile(#RequestParam("file") MultipartFile file) {
}
However, it doesn't seem to work. I keep getting an error saying that the 'Current request is not a multipart request'. Any ideas?
It's not sufficient to specify content-type in frontend you need to do it in controller as well.
You should tell to spring controller what it should consume and also it would be nice to set RequestMethod as POST like this:
#CrossOrigin
#RequestMapping("/UploadFile")
#ResponseBody
public void uploadFile(#RequestParam("file") MultipartFile file, method = RequestMethod.POST, consumes = "multipart/form-data") {
}
I have a form that contains a file and some other input field elements.
Submit is done as follows:
var xhrArgs = {
form: attachmentForm,
handleAs: "json",
load: dojo.hitch(this, this._uploadSuccess),
error: dojo.hitch(this, this._uploadError)
};
var deferred = dojo.io.iframe.send(xhrArgs);
On backend i have a Spring controller listening for this POST request as follows:
#RequestMapping(value="/uploadAttachment.spr", consumes = { "multipart/form-data" })
public String execute(HttpServletRequest request, HttpServletResponse response)
Everything works fine so far.
I would like now to get all request parameters (basically the POST payload) inside a POJO object.
I tried adding a #RequestBody parameter, but it fails with bad request(400):
#RequestMapping(value="/uploadAttachment.spr", consumes = { "multipart/form-data" })
public String execute(HttpServletRequest request, HttpServletResponse response,
#RequestBody AttachmentFormModel model)
I assume it fails because the payload is not in JSON format.
So my question is: what is the best way to automatically map all request parameters into a model object?
I've managed to fix this using #ModelAttribute instead of #RequestBody
I am using Spring MVC 4, and I have a controller with the below mapping/method:
#RequestMapping(value = "/me/bio", method = RequestMethod.POST, consumes = { "multipart/form-data" })
#ResponseBody
public JsonResponse<Boolean> saveProfileBio1(Account account, #RequestPart("file") MultipartFile file, #RequestPart("profile") #Valid ProfileBio profileBio) throws ValidationException, IOException {
...//code here
}
When I submit a multipart form data request it fails with HTTP 400 Bad request with the error " org.springframework.web.multipart.support.MissingS ervletRequestPartException: Required request part 'profile' is not present"
Below is the raw request:
------WebKitFormBoundarynU961NKt3K534rCg
Content-Disposition: form-data; name="profile"
{"profileName":"Zack Smith","profileDescription":"xxx","profileWebLink" :"www.abc","profilePictureUrl":"https://s3.amazonaws.com/xxx-images/default.png","profileTitle":"CTO1"}
------WebKitFormBoundarynU961NKt3K534rCg
Content-Disposition: form-data; name="file"; filename="2013-11-16 21.19.59.jpg"
Content-Type: image/jpeg
As you can see the request clearly has the "profile" part. From my debugging, the issue is that the "profile" request part does not have the "Content-type" set, and DefaultMultipartHttpServletRequest has the below method that requires it to be set and if it returns null the entire request fails with the above error.
#Override
public HttpHeaders getMultipartHeaders(String paramOrFileName) {
String contentType = getMultipartContentType(paramOrFileName);
if (contentType != null) {
HttpHeaders headers = new HttpHeaders();
headers.add(CONTENT_TYPE, contentType);
return headers;
}
else {
return null;
}
}
Trouble is is that I can't seem to find a way to set the content-type on a FormData submit in the browser for each part and seems to be something I can't set, and Spring seems to require it.
Any tips on how to fix this or if this is a bug?
Thanks
I see two options to solve the issue:
On the client: Add the JSON as Blob to FormData, as mentioned here. Background: Blob allows setting the content type (example with angular js):
var formData = new FormData();
formData.append('profile', new Blob([angular.toJson(profile)], {
type: "application/json"}
));
Alternativly on the server (not recommended): overwrite the getMultipartHeaders method of DefaultMultipartHttpServletRequest and configure this in spring. If you are using CommonsMultipartResolver you need to overwrite it as well (due to missing dependency injection point):
new DefaultMultipartHttpServletRequest() {
#Override
public HttpHeaders getMultipartHeaders(String paramOrFileName) {
// your code here
}
}
I was just battling this issue and my solution was to stop using #RequestPart and use #RequestParam instead. If I'm understanding the doc for #RequestPart correctly, it only works out of the box for a few types (such as MultipartFile) but others require an HttpMessageConverter. Also make sure you have a MultipartResolver bean declared. Recommend that it return a CommonsMultipartResolver.
I have an issue using Ajax upload with Spring 3 MVC. I understand that I have to configure multipartResolver bean in spring config, which I've done. Than I can have controller like this
#RequestMapping(value ="/settingsSim")
#ResponseBody
public Map uploadSimSettings(#RequestParam(value="qqfile", required=true) MultipartFile settings) {
Map<String, Object> ret = new HashMap<String, Object>();
return ret;
}
The problem is that when I actually send the request to the server (actually valums Ajax file upload does this for me), I get an Internal server error response and nothing is shown in the logs. I am really scratching my head now, as I cannot figure out the problem.
my solution:
#RequestMapping(value = "/create/upload", method = RequestMethod.POST, consumes="multipart/form-data", produces="application/json")
#ResponseBody()
public String handleImageUpload(#RequestParam(value="qqfile", required=true) MultipartFile[] files,
#ModelAttribute(value="files") List<MultipartFile> filesSession) throws IOException, FileUploadException {
if (files.length > 0) {
filesSession.addAll(Arrays.asList(files));
// store the bytes somewhere
return "{\"success\": true}";
}
else {
return "{\"success\": false}";
}
}
#RequestMapping(value = "/create/upload", method = RequestMethod.POST, consumes="application/octet-stream", produces="application/json")
#ResponseBody()
public String handleImageUploadApplication(HttpServletRequest request,
#ModelAttribute(value="files") List<MultipartFile> filesSession) throws IOException, FileUploadException {
if (request.getInputStream() != null) {
// creamos el fichero temporal
File file = File.createTempFile("file", "valumns",
RepositoryData.getRepositoryData());
FileOutputStream fos = new FileOutputStream(file);
// copiamos contenido
Streams.copy(request.getInputStream(), fos, true);
//TODO:
//filesSession.addAll(Arrays.asList(files));
// store the bytes somewhere
return "{\"success\": true}";
}
else {
return "{\"success\": true}";
}
}
#ExceptionHandler(Exception.class)
#ResponseStatus(value = HttpStatus.SERVICE_UNAVAILABLE)
public void handleException(Exception ex) {
log.error("Ocurrio un error en el album", ex);
}
I had the same problem with the fineuploader (valums), and I tried using request.getInputStream() but did not get it to work.
The #ResponseBody annotation worked but I got the whole body with headers. I thought processing that and stripping off the unwanted chunks was not very elegant.
I looked further and found the solution is this post:
problem with spring ajax file upload
Like it is said, I added the bean configuration for the multipart resolver to my spring configuration
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
</bean>
After that, I could easily retrieve my file using
public #ResponseBody Map ajaxUploadFile(#RequestParam MultipartFile qqfile) { ... }
Don't forget to add the Apache commons-io.jar and commons-fileupload.jar libraries in your project to get it to work
When using valums plugin I solved this problem by using #RequestBody Spring annotation.
You could rewrite your code as follows:
#RequestMapping(value ="/settingsSim",method=RequestMethod.POST)
#ResponseBody
public Map uploadSimSettings(#RequestBody String body) {
/*
some controller logic
*/
}
Note that the variable body will contain the contents of the uploaded file. Also there is no method declaration in your example which means that your method will be mapped to GET request.
P.S. I also had this "no multipart boundary" problem when parsing request with Apache Commons. HttpServletRequest#getParts() returns just an empty collection.
#Tomas I encountered same issue while using the same jquery plugin. Please change the Content-Type in the plugin code to xhr.setRequestHeader("Content-Type", "multipart/form-data"); on my plugin its line 1203, after this its now showing a stack trace, however I am encountering another issue where the logs are printing :
Sep 8, 2011 9:43:39 AM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet dispatcher threw exception
org.apache.commons.fileupload.FileUploadException: the request was rejected because no multipart boundary was found
As per my observation the file upload plugin does not send a multipart file but sends a stream. I could get it to work by declaring the controller method to accept filename as request param qqfile and the second parameter as httprequest. I then did further processing using request.getinputstream. Hope that helps!
Regards,
Pradyumna
I hope that I won't start a topic that's done already but I didn't find any proper answer here nor anywere else.
So here we go:
I use a WebClient to download HTML Code from a webpage, then I send a new request with that WebClient and the WebPage redirects me. Now I want to now where the Site has put me.
The WebClient Class itself doesn't have any suitable properties, I already tried to rewrite the class so that I could get the Response URI but somehow it doesn't work for wp7.
So any ideas how to get the URI where my WebClient got redirected? Or any idea why the application crashes when I want to use my own class:
public class MyWebClient : WebClient
{
Uri _responseUri;
public Uri ResponseUri
{
get { return _responseUri; }
}
protected override WebResponse GetWebResponse(WebRequest request, IAsyncResult result)
{
WebResponse response = base.GetWebResponse(request, result);
_responseUri = response.ResponseUri;
return response;
}
}
}
Thanks in advance!
HttpWebRequest is the solution here, since WebClient is a wrapper around it anyway. Something like this should work for your specific situation:
private HttpWebRequest request;
private bool flagIt = true;
public MainPage()
{
InitializeComponent();
request = (HttpWebRequest)WebRequest.Create("http://google.com");
request.BeginGetResponse(new AsyncCallback(GetData), request);
}
public void GetData(IAsyncResult result)
{
HttpWebRequest request = (HttpWebRequest)result.AsyncState;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);
Debug.WriteLine(response.ResponseUri.ToString());
if (flagIt)
{
request = (HttpWebRequest)WebRequest.Create("http://microsoft.com");
request.BeginGetResponse(new AsyncCallback(GetData), request);
flagIt = false;
}
}
I am initiating the request in the main page constructor and then I am handling it in the callback. Notice how I am getting the ResponseUri - your final destination.
You don't need to handle AllowAutoRedirect if you don't want blocking the redirect and simply getting the URL, like I am doing in the snippet above.