Sending dynamic fieldnames for RequestBody multipart/form-data in spring - java

I am currently doing an experiment to build the API which users can submit freely at their own will without restriction, no boundary on field names and the contents as well. And the API would just print out the inputs in a key,value pairs. For the files, I would just print out the whole bytes of the base64 converted of it.
For example, I have the request A like this:
{
"name": "John Doe",
"lucky_number": 75
}
Then the API will get the output:
Hello user, your first key is name and its value is John Doe, your next key is lucky_number and its value is 75. Thank you for using.
Then, I make another request with the fields below. The image actually was filled with actual image/jpg file.
"pokemon": "pikachu",
"image": <File>JFIFw9d1j3f0881ehfce0cn2e0f2
So, it will print out most likely:
Hello user, your first key is pokemon and its value is pikachi, your next key is image and its value is cApovnquGCaisa1b23IAbqxcaiFoPqR==. Thank you for using..
Can this actually be achieved? As for what I have known, I can make such dynamic request if the request body was formatted in JSON file that Spring can easily get it to the Java Object format. But what about this multipart? And as far as I know, I can get the multipart only with the defined fieldname, and this code below most likely can only handle one file with field file, but what if the user actually send 3 files or even more as there's no boundary as the expected behavior?
#PostMapping("/fun", consumes = { "multipart/mixed", "multipart/form-data" }, produces = {"text/plain"}
public String postForFun(#RequestPart("file") MultipartFile file, #RequestBody Object dynamicFields) {
}

Related

How to send multipart/form-data and nested json in the same request in postman?

I have a REST api that takes data of nested json including multipart file
While testing the REST api through postman I am having problems.
I don't exactly know how to send the diverse types of data that I need - multipart/form-data file and nested json.
I have used REST in each case separately in other projects but I am unable to combine them in one request.
To use multipart/form-data I have to select form-data in the Body, then File from the dropdown in the key field, click on the select files button on the value field and select the file I want to upload.
To use nested json I have to select raw in the dropdown, and select json at the right of it and simply add the nested json in the body.
But how do I combine these two approaches?
I need multipart/form-data as well as nested json in the same request. How do I send these from postman? I am trying various approaches as you can see in the screenshots but I am not getting anywhere.
Thanks in advance
P.S. If it matters, I am using java (spring boot) for the backend.
Your first approach is correct. However to pass the most complicated data it will be a nightmare to do from that location. If passing data from postman is the requirement then you can use the pre-request script in the postman. Below is the example:-
For pre-req, I have kept a basic js object.
Try with this feature.
I followed the above answer and it worked for me.
Step 1: set json data value in pre-request Script.
var data = {
name:"COD Black Ops",
cost:60,
}
pm.variables.set("somedata",JSON.stringify(data));
Step 2: set form values.
enable content type option from (...) like button next to description column in order to set the value of your json field as "application/json".
Step 3: express code for handling form data
const multer = require('multer')
const upload = multer(<options>)
app.post('/stats', upload.single('uploaded_file'), function (req, res) {
// req.file is the name of your file in the form above, here 'uploaded_file'
// req.body will hold the text fields, if there were any
console.log(req.file, req.body)
});

Pass a file to AWS Lambda via API Gateway

I am trying to pass a .csv file (less than 5MB) to a Lambda to perform some processing and I am not sure what would be the best way of doing this. Currently, I pass it as JSON string property and it works but I'm not sure if there are any pitfalls to this approach.
Current API:
{
"fileMetadata1" : "some meta data like a name for the request",
"date": "date file was last modified for example",
...
"fileData", "the actual data of file in String format"
}
Ideally id like "fileData" to be of type InputStream in my input object model, but that didn't work for some reason.
A very common pattern is to put your file to s3, and then make your lambda read it from s3. You can either start the lambda from a s3 event, or by passing it the address of the file to your invocation.
This is generally a better idea, as you won't have to care about input size limitations anymore.

How to post a big string/json using AJAX on Play Framework 1.4.x

I have a JSON that looks more or less like this:
{"id":"id","date":"date","csvdata":"csvdata".....}
where csvdata property is a big amount of data in JSON format too.
I was trying to POST this JSON using AJAX in Play! Framework 1.4.x so I sended just like that, but when I receive the data in the server side, the csvdata looks like [object Object] and stores it in my db.
My first thought to solve this was to send the csvdata json in string format to store it like a longtext, but when I try to do this, my request fails with the following error:
413 (Request Entity Too Large)
And Play's console show me this message:
Number of request parameters 3623 is higher than maximum of 1000, aborting. Can be configured using 'http.maxParams'
I also tried to add http.maxParams=5000 in application.conf but the only result is that Play's console says nothing and in my database this field is stored as null.
Can anyone help me, or maybe suggest another solution to my problem?
Thanks you so much in advance.
Is it possible that you sent "csvdata" as an array, not a string? Each element in the array would be a separate parameter. I have sent 100KB strings using AJAX and not run into the http.maxParams limit. You can check the contents of the request body using your browser's developer tools.
If your csvdata originates as a file on the client's machine, then the easiest way to send it is as a File. Your controller action would look like:
public static void upload(String id, Date date, File csv) {
...
}
When Play! binds a parameter to the File type, it writes the contents of the parameter to a temporary file which you can read in. (This avoids running out of memory if a large file is uploaded.) The File parameter type was designed for a normal form submit, but I have used it in AJAX when the browser supported some HTML5 features (File API and Form Data).

How to upload a file and JSON data in Postman?

I am using Spring MVC and this is my method:
/**
* Upload single file using Spring Controller.
*/
#RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
public #ResponseBody ResponseEntity<GenericResponseVO<? extends IServiceVO>> uploadFileHandler(
#RequestParam("name") String name,
#RequestParam("file") MultipartFile file,
HttpServletRequest request,
HttpServletResponse response) {
if (!file.isEmpty()) {
try {
byte[] bytes = file.getBytes();
// Creating the directory to store file
String rootPath = System.getProperty("catalina.home");
File dir = new File(rootPath + File.separator + "tmpFiles");
if (!dir.exists()) {
dir.mkdirs();
}
// Create the file on server
File serverFile = new File(dir.getAbsolutePath() + File.separator + name);
BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(serverFile));
stream.write(bytes);
stream.close();
System.out.println("Server File Location=" + serverFile.getAbsolutePath());
return null;
} catch (Exception e) {
return null;
}
}
}
I need to pass the session id in postman and also the file. How can I do that?
In postman, set method type to POST.
Then select
Body -> form-data -> Enter your parameter name (file according to your code)
On the right side of the Key field, while hovering your mouse over it, there is a dropdown menu to select between Text/File. Select File, then a "Select Files" button will appear in the Value field.
For rest of "text" based parameters, you can post it like normally you do with postman. Just enter parameter name and select "text" from that right side dropdown menu and enter any value for it, hit send button. Your controller method should get called.
The Missing Visual Guide
You must first find the nearly-invisible pale-grey-on-white dropdown for File which is the magic key that unlocks the Choose Files button.
After you choose POST, then choose Body->form-data, then find the File dropdown, and then choose 'File', only then will the 'Choose Files' button magically appear:
Maybe you could do it this way:
Like this :
Body -> form-data -> select file
You must write "file" instead of "name"
Also you can send JSON data from Body -> raw field. (Just paste JSON string)
I got confused after seeing all of the answers, I couldn't find any proper screenshot to bring the Content Type column. After some time, I found it by my own. Hope this will help somebody like me.
Here is the steps:
click on red marked area of postman.
Now check the green marked option (Content Type).
Now change the search content type, in the yellow marked area.
In my case:
invoice_id_ls (key) contains the json data.
documents contains the file data.
placed_amount contains normal text string.
Select [Content Type] from [SHOW COLUMNS] then set content-type of "application/json" to the parameter of json text.
Don't give any headers.
Put your json data inside a .json file.
Select your both files one is your .txt file and other is .json file
for your request param keys.
If somebody wants to send json data in form-data format just need to declare the variables like this
Postman:
As you see, the description parameter will be in basic json format, result of that:
{ description: { spanish: 'hola', english: 'hello' } }
Kindly follow steps from top to bottom as shown in below image.
At third step you will find dropdown of type selection as shown in below image
Body > binary > Select File
If you need like
Upload file in multipart using form data and send json data(Dto object) in same POST Request
Get yor JSON object as String in Controller and make it Deserialize by adding this line
ContactDto contactDto = new ObjectMapper().readValue(yourJSONString, ContactDto.class);
If somebody needed:
body -> form-data
Add field name as array
Use below code in spring rest side :
#PostMapping(value = Constant.API_INITIAL + "/uploadFile")
public UploadFileResponse uploadFile(#RequestParam("file") MultipartFile file,String jsonFileVo) {
FileUploadVo fileUploadVo = null;
try {
fileUploadVo = new ObjectMapper().readValue(jsonFileVo, FileUploadVo.class);
} catch (Exception e) {
e.printStackTrace();
}
If you want to make a PUT request, just do everything as a POST request but add _method => PUT to your form-data parameters.
The way to send mulitpart data which containts a file with the json data is the following, we need to set the content-type of the respective json key fields to 'application/json' in the postman body tab like the following:
You can send both Image and optional/mandatory parameters.
In postman, there is Params tab.
I needed to pass both: a file and an integer. I did it this way:
needed to pass a file to upload:
did it as per Sumit's answer.
Request type : POST
Body -> form-data
under the heading KEY, entered the name of the variable ('file' in my backend code).
in the backend:
file = request.files['file']
Next to 'file', there's a drop-down box which allows you to choose between 'File' or 'Text'. Chose 'File' and under the heading VALUE, 'Select files' appeared. Clicked on this which opened a window to select the file.
2.
needed to pass an integer:
went to:
Params
entered variable name (e.g.: id) under KEY and its value (e.g.: 1) under VALUE
in the backend:
id = request.args.get('id')
Worked!
For each form data key you can set Content-Type, there is a postman button on the right to add the Content-Type column, and you don't have to parse a json from a string inside your Controller.
first, set post in method and fill link API
Then select Body -> form-data -> Enter your parameter name (file according to your code)
If you are using cookies to keep session, you can use interceptor to share cookies from browser to postman.
Also to upload a file you can use form-data tab under body tab on postman, In which you can provide data in key-value format and for each key you can select the type of value text/file. when you select file type option appeared to upload the file.
If you want the Id and File in one object you can add your request object to a method as standard and then within Postman set the Body to form-data and prefix your keys with your request object name. e.g. request.SessionId and request.File.
The steps of uploading a file through postman along with passing some input data is very well discussed in below blog along with the screenshot. In this blog, the api code is written in node js. You can go through it once to have more clarity.
https://jksnu.blogspot.com/2021/09/how-to-create-post-request-with.html
At Back-end part
Rest service in Controller will have mixed #RequestPart and MultipartFile to serve such Multipart + JSON request.
#RequestMapping(value = "/executesampleservice", method = RequestMethod.POST,
consumes = {"multipart/form-data"})
#ResponseBody
public boolean yourEndpointMethod(
#RequestPart("properties") #Valid ConnectionProperties properties,
#RequestPart("file") #Valid #NotNull #NotBlank MultipartFile file) {
return projectService.executeSampleService(properties, file);
}
At front-end :
formData = new FormData();
formData.append("file", document.forms[formName].file.files[0]);
formData.append('properties', new Blob([JSON.stringify({
"name": "root",
"password": "root"
})], {
type: "application/json"
}));
See in the image (POSTMAN request):
Click to view Postman request in form data for both file and json
To send image along with json data in postman you just have to follow the below steps .
Make your method to post in postman
go to the body section and click on form-data
provide your field name select file from the dropdown list as shown below
you can also provide your other fields .
now just write your image storing code in your controller as shown below .
postman :
my controller :
public function sendImage(Request $request)
{
$image=new ImgUpload;
if($request->hasfile('image'))
{
$file=$request->file('image');
$extension=$file->getClientOriginalExtension();
$filename=time().'.'.$extension;
$file->move('public/upload/userimg/',$filename);
$image->image=$filename;
}
else
{
return $request;
$image->image='';
}
$image->save();
return response()->json(['response'=>['code'=>'200','message'=>'image uploaded successfull']]);
}
That's it hope it will help you

Retrieve JSON attachment and its attributes

Background:
I have stored a JSON document (id: 160d7237a5fd00501f4654a6c8b42f38) in a CloudantDB and put an attachment against the document. As you can see that below JSON structure has one attachment (i.e. Rajiv.jpg) associated with it.
I want to retrieve the JSON attachment object (JPEG). Can someone help me how I can transform the below JSON structure to a Java POJO class and retrieve the attachment using the same ? What would be the definition of the POJO class. Thanks in advance.
I want to show the JPEG file in the UI screen via a webservice which will retrive the JPEG from CLoudantDB and pass it to UI.
{
"_id": "160d7237a5fd00501f4654a6c8b42f38",
"_rev": "3-695e52989827cd9e203ff9f506eaf7df",
"Customer_Id": "2",
"_attachments": {
"Rajiv.jpg": {
"content_type": "image/jpeg",
"revpos": 2,
"digest": "md5-/78IzjPUu7nkbVbSXBF2Xg==",
"length": 39712,
"stub": true
}
}
}
The JSON you've got doesn't include the actual attachment - just metadata about it.
From the documentation:
To retrieve an attachment, make a GET request to https://$USERNAME.cloudant.com/$DATABASE/$DOCUMENT_ID/$ATTACHMENT. The body of the response is the raw content of the attachment.
So in this case it sounds like you'd make a request to https://[...].cloudant.com/[...]/160d7237a5fd00501f4654a6c8b42f38/Rajiv.jpg
The documentation seems confusing as to whether the response will actually be JSON with Base64 data, or just the data - but try it and see.
You don't need a POJO to parse the original data shown in your question; whatever parser you use is likely to provide a "dynamic" view allowing you to fetch fields by name: just fetch the _attachments field, and then iterate over the fields within the resulting object.

Categories

Resources