ExtJS uploading file results in Bad Request error: Required MultipartFile parameter 'file' is not present - spring

I have seen fair amount of threads regarding bad request errors upon file upload, however unlike for others, I am sure that Spring is not at fault here, as I am able to upload file via curl without an issue: curl -X POST -v http://localhost:8080/rest/datasets/ -T test.xlsx
ExtJS uploader:
{
xtype: 'filefield',
fieldLabel: 'Select file',
name: 'file',
fieldName : 'file',
listeners: {
change: function(filefield, value, eOpts) {
var form = filefield.up('form').getForm();
form.submit({
url: '/rest/datasets',
headers : {
'Accept' : '*/*',
'Content-Type' : 'multipart/form-data'
},
waitMsg: 'Uploading'
});
}
}
}
Spring controller
#RestController
#RequestMapping("rest/datasets")
public class DatasetController {
#RequestMapping(method = RequestMethod.POST)
public String uploadFile(
#RequestParam("file") MultipartFile file) {
...
}
}
I am using ExtJS 6.0.1 and Spring Boot 1.3.3

I don't believe it's ExtJS at fault here. I checked your sample in sencha fiddle, and it seems that parameter "file" does exist when posting.
------WebKitFormBoundaryCL4R6o6o2MXXQcAx
Content-Disposition: form-data; name="file"; filename="Capture1.PNG"
Content-Type: image/png
------WebKitFormBoundaryCL4R6o6o2MXXQcAx--
You could also try: Spring mvc: HTTP Status 400 - Required MultipartFile parameter 'file' is not present

Related

Inertiajs not sending inputs through parameters [Laravel 9]

I'm sending a put/patch request to backend (Inertiajs to Laravel). but the parameter bag is empty and all the inputs shows up in content attribute of request object.
// in frontend [Inertiajs]
form.patch(route('posts.update', props.post.id), options);
// form.put(route('posts.update', props.post.id), options); // same as patch method
// in backend Laravel
dd(request());
result:
Illuminate\Http\Request :
request:
parameters: []
content:
------WebKitFormBoundaryLAUcPkq3YTjgwsCM
Content-Disposition: form-data; name="title"
"some title"
now dd(request('title')) give me null.
what should I do to the code for sending the inputs through request parameters?
There is some multipart limitations. As Inertia says here, uploading files using a multipart/form-data request is not natively supported in some languages for the put, patch or delete methods. The workaround here is to simply upload files using post instead.
In your case, would look something like this:
form.post(route('posts.update', {
_method: 'put',
postId: props.post.id,
})
* Do it like this if you want to preserve the scroll:
form.post(route('posts.update', {
_method: 'put',
postId: props.post.id,
}, {
preserveScroll: true,
})

asp.net core Ajax requests gives 400 bad request but POSTMAN works

I am facing trouble with ajax request in asp.net core blazor application. I have tried almost everything i can find on stackoverflow related to ajax post call results in 400 bad request
I have following controller
[Route("api/{controller}/{action}/{id?}")]
public class BoldReportsAPIController : ControllerBase, IReportController
{
// Report viewer requires a memory cache to store the information of consecutive client request and
// have the rendered report viewer information in server.
private IMemoryCache _cache;
// IHostingEnvironment used with sample to get the application data from wwwroot.
private IWebHostEnvironment _hostingEnvironment;
public BoldReportsAPIController(IMemoryCache memoryCache, IWebHostEnvironment hostingEnvironment)
{
_cache = memoryCache;
_hostingEnvironment = hostingEnvironment;
}
// Post action to process the report from server based json parameters and send the result back to the client.
[HttpPost]
public object PostReportAction([FromBody] Dictionary<string, object> jsonArray)
{
return ReportHelper.ProcessReport(jsonArray, this, this._cache);
}
}
When i make request with postman it works fine as shown below.
But when i make ajax call it gives 400 bad request error.
I have literally replaced original ajax call with the code generated from postman but that code doesn't work also.
var settings = {
"async": true,
"crossDomain": true,
"url": "https://localhost:44313/api/BoldReportsAPI/PostReportAction",
"method": "POST",
"headers": {
"content-type": "application/json",
"cache-control": "no-cache",
"postman-token": "fbed680d-0143-ab86-24e6-176c16d713bf"
},
"processData": false,
"data": "{\"reportAction\":\"ReportLoad\",\"isReloadReport\":false,\"controlId\":\"report-viewer\",\"reportPath\":\"sales-order-detail\",\"enableVirtualEvaluation\":false,\"reportServerUrl\":\"\",\"processingMode\":\"remote\",\"locale\":\"en-US\",\"accessInternalValue\":false,\"customBrandSettings\":{\"hideHelpLink\":false,\"customDomain\":\"https://help.boldreports.com\",\"customBrandName\":\"Bold Reports\",\"customLinks\":[{\"name\":\"ESLicenseMessage\",\"url\":\"/licensing/license-token/\"}]}}\r\n"
}
$.ajax(settings).done(function (response) {
console.log(response);
});
It was due to ant forgery token. Apparently, ABP automatically adds antiforgery token so after adding
[IgnoreAntiforgeryToken(Order = 2000)]
to my action method, issue was resolved.
But it feels like I am breaking security.
While using ValidateAntiForgeryToken, you have to add the headers for the Report Viewer API interaction. You can refer to the below article to add the headers for your Report Viewer interaction. These need to be added with the ReportViewer introp.
https://help.boldreports.com/embedded-reporting/javascript-reporting/report-viewer/handle-post-actions/#add-custom-header-in-ajax-request

Angular 8 can't upload formdata/multi-part to server

I'm trying to upload a xlsx file to server, but I receive two different errors, whether I specify the contentType in the http request header or not. If I specify "Content-type: multipart/form-data" I get the following error:
FileUploadException: the request was rejected because no multipart
boundary was found
Then, if I do not specify the content type (as proposed in different answers), I get this error:
current request is not a multipart request
This is what I do to upload the file. HTML (input fired by a button that calls an uploadFile() method):
<input type="file" #fileUpload id="fileUpload" name="fileUpload" accept=".xlsx" style="display:none;" />
.ts:
uploadFile() {
const fileUpload = this.fileUpload.nativeElement;
fileUpload.onchange = () => {
this.file = fileUpload.files[0];
this.uploadFileToServer();
};
fileUpload.click();
}
uploadFileToServer() {
const formData = new FormData();
formData.append('file', this.file);
this.importService.uploadFile(formData).subscribe(d => {
});
}
In the service the method does this:
this.http.post(
apiUrl,
formData,
options
);
where in options there are the specified headers:
let applicationHeaders = new HttpHeaders();
applicationHeaders = applicationHeaders.append('Content-type', 'multipart/form-data');
multipart or blank.
In the POST request in the request payload I have:
------WebKitFormBoundarytNckytdr7I8wQcuc
Content-Disposition: form-data; name="file"; filename="Template (2).xlsx"
Content-Type: application/octet-stream
------WebKitFormBoundarytNckytdr7I8wQcuc--

Content type 'text/plain;charset=UTF-8' not supported error in spring boot inside RestController class

I got the following #RestController inside a spring boot application :
#Data
#RestController
public class Hello {
#Autowired
private ResturantExpensesRepo repo;
#RequestMapping(value = "/expenses/restaurants",method = RequestMethod.POST,consumes =MediaType.APPLICATION_JSON_VALUE ,
headers = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public void hello(#RequestBody ResturantExpenseDto dto)
{
Logger logger = LoggerFactory.getLogger("a");
logger.info("got a request");
ResturantExpenseEntity resturantExpenseEntity = new ResturantExpenseEntity();
resturantExpenseEntity.setDate(new Date(System.currentTimeMillis()));
resturantExpenseEntity.setName(dto.getName());
resturantExpenseEntity.setExpense(dto.getExpense());
repo.save(resturantExpenseEntity);
}
}
When I try to send request from restClient/RestedClient (both addons of mozila) I get the following error :
{
"timestamp": 1512129442019,
"status": 415,
"error": "Unsupported Media Type",
"message": "Content type 'text/plain;charset=UTF-8' not supported",
"path": "/expenses/restaurants"
}
This eror states that the end point doesnt support Json content,But I did
put
consumes =MediaType.APPLICATION_JSON_VALUE
inside #RequestMapping annotation
What am I missing?
Late response but I had the same problem posting the answer it might be useful to someone so I installed Postman and then just change your Content-Type to application/json
If the request is made like this: then it will resolve the issue.
curl -X PUT -H 'Content-Type: application/json' -i http://localhost:8080/spring-rest/api/employees/500 --data '{
"name": "abc",
"email": "abc.a#gmail.com",
"salary": 10000
}'
I see the headers are proper: headers = MediaType.APPLICATION_JSON_VALUE
but when the request is made, at that time we need to inform the handler that its a application/json mime type.
This is late too, but in RESTClient(Mozilla addon), you can add Content-Type: application/JSON from the Headers dropdown menu and even at the response side change it to JSON format
if you are using html with ajax.Check the request header and the payload. Make sure the ajax has the following fields
url : your url
type : 'post',
dataType: "json",
contentType: "application/json; charset=utf-8",
data : JSON.stringify( your payload )
if the ajax call has the following fields remove them and try again
processData : false,
contentType : false,

PDF File is not getting downloaded. Ajax call failing with transfer-encoding as chunked

I am working on an application which allows the user to download a file on a button click. on click of a button I make an ajax call and that calls a spring controller. Inside that spring controller i have written a function as below:
#RequestMapping(value="/downloadFile", method=RequestMethod.GET)
public #ResponseBody String dowloadPDF(final HttpSession session, final HttpServletResponse response,#RequestParam(value="param1", required=true)final String param1,#RequestParam(value="param2",required=true)final String param2,#RequestParam(value="param3", required=true)final String param3,#RequestParam(value="fileName",required=true)final String fileNameRecieved){
final String fileName = fileNameRecieved.trim();
final String requestedFile = getPath(param1,param2,param3,fileName);
try{
File pdfFile= new File(requestedFile);
final InputStream inputStream = new FileInputStream(pdfFile);
response.setContentType("application/pdf");
response.setHeader("Content-Disposition","attachment;filename="+fileName);
IOUtils.copy(inputStream, response.getOutputStream());
response.flushBuffer();
inputStream.close();
}catch(Exception exception){
System.out.println("stckTrace : "+exception.getStackTrace());
exception.printStackTrace();
}
return "success";
}
and the ajax call written on a button click is as below.
$.ajax({
url : "downloadFile",
method : "GET",
dataType: "json",
contentType: 'application/pdf',
'Transfer-Encoding': 'chunked',
sync:true,
data:{
"param1" :param1,
"param2":param2,
"param3" :param3,
"fileName": fileName
},
success : function(response) {
alert(response);
},
error : function(e) {
alert('Error: ' + e.getAllResponseHeaders());
}
});
The problem is my controller is getting called and executed without giving any exceptions. but no file was not downloaded and also i am getting error in the response of ajax call stating that
"Server: Apache-Coyote/1.1
Content-Disposition: attachment;filename=GATE-CS 2004.pdf
Content-Type: application/pdf
Transfer-Encoding: chunked
Date: Thu, 05 Feb 2015 16:33:22 GMT
"
Any one can please help me on this, I have changed the content type in ajax call as well, still it is not working.
One problem seems to be related with dataType and contentType in the ajax call.
I think you have swapped their value in ajax call.As per your problem description ,their value should be.
dataType:'application/pdf','Transfer-Encoding': 'chunked'
contentType : "json"//but you don't need to use it,because you are not sending the json data

Resources