I'd like to create an endpoint which accepts any amount od different files from user.
For example:
Then, I'd like to receive it in my controller as a Map<String, FilePart> (or any other structure from which I'll know which file is which):
{
"file1": "cactus-logo.png",
"file2": "logo.png",
"file3": "logo.png" (this one is actually different than file2 but has the same name)
}
I tried some combinations of #RequestPart...
When I do:
#RequestPart Map<String, FilePart> files
or
#RequestPart MultiValueMap<String, FilePart> files
I'm getting:
org.springframework.web.server.ServerWebInputException: 400 BAD_REQUEST "Required request part 'files' is not present"
When I do:
#RequestPart("files") List<FilePart> files
I need to submit files like that:
And then I don't have the information which file is which (if they have the same name):
Finally, I can do:
#RequestPart("file1") FilePart file1,
#RequestPart("file2") FilePart file2,
#RequestPart("file3") FilePart file3
And then it works as expected, but with that, it's possible to submit always only 3 files. I'd like to submit any number of files.
As suggested in comments:
#PutMapping(value = "/{component}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public void upload(
#RequestParam Map<String, MultipartFile> files
) throws IOException {
and the map is always empty:
You should use #RequestParam
#PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public void upload(#RequestParam Map<String, MultipartFile> body) {
}
Then post via form-data media ie:
file1: select file
file2: select file
file3: select file
....
I did not mention I'm using reactive webflux, thus solution posted by #Toàn Nguyễn Hải does not work in my case. I believe it works in non-reactive applications.
For web flux, the following works:
To be fair, I won't accept any answer, because both of them are fine.
Thanks!
Related
I have an API that accepts a multi part form data (json body and file upload). My API works when I use Postman but Swagger does not seem to like it. Is there a way to allow for multipart payload? I know I can accepts the json body as a binary file upload, but I would prefer to allow the user to enter the json body into a text area in Swagger. Here is my example code:
#PostMapping(value = "/myPost", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<MyResult> createPost(
#RequestPart(value = "body", required = true) MyDTO myDto,
#RequestPart(required = false) MultipartFile[] attachments) {
//my code
}
Swagger will then show a Text area called Body, which has my MyDTO schema and file attachment form. When I submit, I get this error in my Spring Boot API:
org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/octet-stream' not supported
I can change the RequestParts to this:
#RequestPart(value = "body") #Parameter(schema = #Schema(type = "string", format = "binary")) final MyDTO myDTO ,
#RequestPart(value = "file", required = false) final MultipartFile[] attachments
And this will work, but instead of having a Body text area, which displays the MyDTO Schema, Swagger just shows two file upload forms (the Body upload works by putting the JSON payload into a json file and uploading that). While it will work, it is an inconvenience to the user, as they can't just copy in the json payload and instead have to create a separate json file. Is there a way to allow a multip part form to have both a json payload and a file attachment?
thanks
I am creating a Spring Cloud Function that I want to give two inputs, an id and a Multipart file (CSV file) but I am having trouble.
If I choose to send a post with a multipart file the function won't recognise this and gives an error like Failed to determine input for function call with parameters:
With the Postman request being this:
#Bean
public Function<MultipartFile, String> uploadWatchlist() {
return body -> {
try {
return service.convert(body);
}
}
}
I have tried using something more akin to Spring MVC like a request entity object but no luck.
The backup I have (other than Python haha) will be using the binary data post so it will just be a string that has the contents of the file which does work, but requires me to append the id inside to each row of the csv which is a bit messy.
There are other solutions but trying to get this working as Java lambdas are what we want to try and use as first choice.
The infrastructure will be to fix up a manual file upload/verification process that is tedious at the moment and looks like: postman -> load balancer -> lambda -> ecs
The postman/load balancer part will be replaced in future. Ideally have the lambda sorted in Java taking in a file and id.
Thanks for any help :)
Within the form of a web page built with VUE.JS, a GET request is mounted with Axios.
And depending on the value of some of the form's fields, may have special characters and accents.
For example, if in the surname form field, the user writes 'Ruíz', the request is mounted like this:
http://localhost:9000/someController?surname=Ru%C3%ADz
It seems that 'í' is converted to %C3%AD
This is what I have on Java side, in the controller:
#RequestMapping(method = RequestMethod.GET)
#ResponseBody
public SignerQueryResponse getSignerList(
#RequestParam(value = "surname", required = false) String surname,
HttpServletRequest request) {
//... all stuff
}
How can this be corrected?
Do I have to put something on the server side? .. in the Java Controller ??
... something related to ISO-8859-1 encoding??
Thanks
I found a solution, using org.apache.commons.lang.StringEscapeUtils.unescapeHtml().
But I dont know if exists another more "cleaner", based on #annotations for example.
System.out.println(surname); //This gives me unproper: Ruíz
String unescapedSurname = StringEscapeUtils.unescapeHtml(surname);
System.out.println(unescapedSurname); //This gives me the proper: Ruíz
It's about uploading xlsx file. Initially im getting xlsx file as javax.servlet.http.Part and trying to convert as ByteArrayResource Since i need to pass via RestTemplate.
new ByteArrayResource(IOUtils.toByteArray(input.getFile().getInputStream())
Here input.getFile() is javax.servlet.http.Part
As im converting here into ByteArrayResource and sending back to another Layer for business logic, can i get filename from ByteArrayResource ?
Anyhow we can get filename from Part, I want to know is that possible to get filename from ByteArrayResource or ByteArray ?
This is late but if anyone is still looking for an answer.
ByteArrayResource doesn't have any filename by default. See the super class method AbstractResource.getFileName(), it returns null. So until you set the name explicitly while creating ByteArrayResource, it will remain null.
You can achieve this like
ByteArrayResource resource = new ByteArrayResource(bytearray) {
#Override
public String getFilename() {
return "somename";
};
}
Now how to use the actual file name instead of "somename". If you're using Spring, you can define a method in your controller accepting Multipart as an argument.
public ResponseEntity<byte[]> handleFileOperation(Multipart file) {}
Once you get the MultipartFile instance, you can use it the way you want.
You'll probably need to use FileNameAwareByteArrayResource as outlined in Spring-boot MultipartFile issue with ByteArrayResource.
You'll be able to get the filename from it then.
Hello i'm trying create an application allowing me host any kind of file.
In order to do it i'm exececuting following magic:
#RequestMapping(value = "/files/{file_name}", method = RequestMethod.GET)
#ResponseBody
public FileSystemResource
getFile(
#PathVariable("file_name") String fileName) {
System.out.println(fileName);
String filePath = "./files/";
return new FileSystemResource(new File(filePath+fileName));
}
But this approach brings three unwanted problems:
Some random data is beeing appended to the file
The file gets opened in the browser window instead of beeing
downloaded - i've tried to hack this using something like
produces = "application/octet-stream"
but it only resulted in 406 error.
The test.txt is beeing truncated into test, i found a walkaround in providing the app with test.txt/ as fileName but it looks a bit messy.
As stated on spring manual
As with #RequestBody, Spring converts the returned object to a
response body by using an HttpMessageConverter
I think your problem is spring doesn't come with a HttpMessageConverter than can process FileSystemResource.
A list of builtin HttpMessageConverter is available here. I suggest you try converting your response into byte array somehow, maybe it will pick ByteArrayHttpMessageConverter instead and help solve your issue
I used code like this to return image
#RequestMapping(value = "/image/{id}", method = RequestMethod.GET)
public String getImage(... HttpServletResponse response) {
response.setContentType(image/png);
(response.getOutputStream()).write(imageByteArray);
}
I think you have to define proper mime type and send your data to response.