uploading file using Restassured - java

I would like to upload a file using Java and the RestAssured library. Does anyone know how i can use this library to upload a file to a field?
When using Postman, i just make the call to the endpoint and add in the Body section key=upload and value has a "Choose files" button.
How can i upload a file to a field using Restassured? I already have methods that make the body of the request and set all parameters for it, like here:
public CustomizationSetClientField(String clientId, String fieldSetName, String version, String fieldName, String name, String type, String value, String language, String role){
this.body.put("name", name);
this.body.put("type", type);
this.body.put("value", value);
this.url = Config.getByName("customization_url");
this.pathTemplate = Config.getByName("customization_set_client_field");
this.path = Utils.createPath(pathTemplate, clientId, fieldSetName, version, fieldName);
this.role = role;
}
Now this is for setting fields, but i have no idea how to use Restassured with uploads, can you please show me how?

You're probably looking for multipart file uploads. For example:
given().
multiPart("file", new File("/path/to/file")).
when().
post("/upload");

To upload a file using REST API it require 'Content-Type' as 'multipart/form-data'.
Now you need to understand with the developer that are they allowing to directly passing the file to API or need to convert the file content to Byte Array.
If require to convert into byte then you can use the below code
Map<String, String> headers = new HashMap<String, String>();
headers.put("Content-Type", "multipart/form-data");
byte[] fileContent = FileUtils.readFileToByteArray(new File(filePath));
RestAssured.given().headers(headers).body(fileContent ).post(url);
else you can try directly with the code shared by Johan in another comment.

Related

How do I make a post request with dynamic values for some attributes stored in external JSON file?

I have a BDD automation framework setup with Selenium WebDriver and Cucumber with Java. I have configured Rest Assured and I am currently using one JSON payload which is stored in an external JSON file. I am directly reading this JSON file into byte array and then converting the same to String and sending the payload to a post request.
Till now, everything was static and hence, this was working without any issue. However, now the requirement is to send a couple of attributes with dynamic values everytime I make a post call. I know how to send a complete dynamic payload using POJOs but I am looking for a different solution where I can read the payload from the same JSON file and can send dynamic values for few required attributes. Please let me know if this is possible.
Attaching the code for reference.
File which reads the JSON file and sends the payload to post request
public class AddOrderAPIActions {
ConfigReader configReader = new ConfigReader();
Properties prop;
public AddOrderAPIActions() {
prop = configReader.init_prop();
}
//Setting up the API URI
public void setURI() {
String URI = prop.getProperty("apiURI");
RestAssured.baseURI = URI;
}
//Sending the request payload via POST method
public String sendRequestPayload() throws IOException {
//read data from local JSON file then store in byte array
byte[] b = Files.readAllBytes(Paths.get("./src/test/resources/data/addOrder.json"));
//convert byte array to string
String bdy = new String(b);
//input details with header and body
Response response = given().header("Content-type", "application/json").queryParam("api_key", prop.getProperty("apiKey")).body(bdy)
//adding post method
.when().post().then().log().all().extract().response();
JsonPath jp = response.jsonPath();
String shipmentNumber = jp.get("data.shipmentDetails[0].shipmentNumber");
System.out.println("Shipment Number is "+ shipmentNumber);
return shipmentNumber;
}
}
The JSON file with payload
[
{
"originDetails": {
"originCode": "Dynamic_Value",
"originStartTime": "",
"originEndTime": "",
"senderName": "Origin Name",
"senderContactNumber": "9999999999",
"senderAddress": "Bali, Indonesia",
"senderPincode": "201001",
"senderCity": "Delhi",
"senderCountry": "India"
},
]
Here, I want to send a dynamic value for "originCode" attribute and rest of the attributes should be sent as read from the JSON file.
Thanks in advance.

Assign String-Data to a URL-Object

Is it possible to assign string-data to a java.net.URL?
I'm using an API who's method only accept an URL-Parameter. But i already have the content.
String content = "some text data";
URL url = createURLWithContent(content);
MyApi.handleContent( url );
the createURLWithContent()-Method should create URL-object that containing the data from content, so when URL.getContent() is called, the String (or a Stream containing the String) is returned.
I think I've seen something like this years ago.
Write the content to a file then provide a file: URL, e.g.
public static URL createURLWithContent(String content) throws IOException {
Path tempFile = Files.createTempFile("UrlContent", null);
tempFile.toFile().deleteOnExit();
Files.writeString(tempFile, content);
return tempFile.toUri().toURL();
}
This will return a URL like this:
file:/C:/path/to/temp/UrlContent5767435257817348076.tmp
If your program is long-running, you should handle the deletion of the temporary file yourself, after the API call, rather than rely on deleteOnExit().
If you don't want the content on disk, you could alternatively implement your own in-memory URLStreamHandler, and specify it when creating the URL using the URL(String protocol, String host, int port, String file, URLStreamHandler handler) constructor. This is a lot more involved and beyond the scope of this answer.

download a file from rest api is giving me some garbage value

I am trying to download a file from rest API, I am writing code in Java and react. but when i call that rest api it is not downloading that file instead gives me some garbage
#POST
#Path("/{loginId}")
#Produces(MULTIPART_FORM_DATA)
#Consumes(APPLICATION_JSON)
public Response downloadExportedFile(#PathParam("loginId") String loginId, ExportFileDTO fileDetails) {
File exportFolder = new File("C://directory");
File[] listOfFiles = exportFolder.listFiles();
for (File listOfFile : listOfFiles) {
if (listOfFile.getName().equals(fileDetails.getFileName())) {
InputStream is = new FileInputStream(listOfFile.getAbsolutePath());
byte[] buffer = IOUtils.toByteArray(is);
return Response.ok(listOfFile)
.header("content-disposition", "attachment; filename=" + new File(listOfFile.getName()).getName())
.type(MediaType.APPLICATION_OCTET_STREAM_TYPE).build();
}
}
It should download the file instead it is giving me output as
PK!b�h^�[Content_Types].xml �(����N�0E�H�C�-Jܲ#5��Q>�ēƪc[�ii����B�j7���{2��h�nm���ƻR����U^7/���%��rZY�#1__�f��q��R4D�AJ�h>����V�ƹ�Z�9����NV�8ʩ����ji){^��-I�"{�v^�P!XS)bR�r��K�s(�3�`c�0��������7M4�����ZƐk+�|\|z�(���P��6h_-[�#�!���Pk���2n�}�?�L��� ��%���d����dN"m,�ǞDO97�~��ɸ8�O�c|n���E������B��!$}�����;{���[����2���PK!�U0#�L_rels/.rels �(���MO�0��H�����ݐBKwAH�!T~�I����$ݿ'T�G�~����<���!��4��;#�w����qu*&r�Fq���v�����GJy(v��*����K��#F��D��.W ��=��Z�MY�b���BS�����7��ϛז��
?�9L�ҙ�sbgٮ|�l!��USh9i�b�r:"y_dl��D���|-N��R"4�2�G�%��Z�4�˝y�7 ë��ɂ�����PK!
You have to change the associated mimetype by changing the the parameter of the #Produces annotation which basically describes what type of data you transmit in your response.
It should become:
#Produces("application/vnd.ms-excel")
According to this other stackoverflow question you should change the #Produces annotation to #Produces(MediaType.APPLICATION_OCTET_STREAM).
According to this second stackoverflow question you are asking an impossible question.
Out of curiosity I reproduced your problem here : see the full gist
If you change #POST to #GET it starts working
If you keep #POST, it has to be posted from a real form and can't post application/json
Finally, posting application/json means React is doing a programmatic XmlHTTPRequest. The above gist shall convince you there is no user prompt in that case
When you say it 'is giving me output', you're not telling where and how the post was requested . You will have to adapt that part.
actually It is APPLICATION_OCTET_STREAM response for a file. we have to handle download functionality at client side AS per Nate's answer here, the response of Ajax request is not recognized by a browser as a file. It will behave in the same way for all Ajax responses. You need to trigger the download popup manually.
downloadFile(fileDetails) {
let username = getUserName();
return fetch(`/files/${username}`, {
method: 'POST',
body: JSON.stringify(fileDetails)
}).then(response => {
return response.blob();
}).then(response => {
let blob = new Blob([response], {type: 'application/octet-stream'});
let fileUrl = window.URL.createObjectURL(blob);
Files.triggerDownload(fileUrl, fileDetails.fileName);
}).catch((error) => {
//myerror
});
}
static triggerDownload(url, fileName) {
let a = document.createElement('a');
a.setAttribute('href', url);
a.setAttribute('download', fileName);
a.click();
}
This will download the file at client machine

converting long xml file into string

I am working on a project where i have to convert XML file in the server and then send them into a JSON form in the client side
The problem is when I have a large XML document since parsing will surpass the limit size of the string.
I even tried changing string into Byte[] but the problem my angular client side accept only JSON form
#RequestMapping(value = "/{var1}/{var2}", method = RequestMethod.GET)
public ResponseEntity<byte[]> getGraph(#PathVariable("var1") String var1, #PathVariable("var2") String var2) {
byte[] result = loadUnloadWorkflow.loadWorkflow("AMAZONTEST", "FR");
return new ResponseEntity<byte[]>(result, HttpStatus.OK);
}
is there a way to parse any XML file whatever it's size into string ?
You could try to convert the XML to an object and then, convert the object to json. What about that?

Downloaded file from server is different than original one saved previously

I cannot find out why the mp3 file is different after download from my server than original one saved previously there.
This is my controller method. The content of file (byte[] content) is identical with original file on this stage - the original file is the same as file retrieved from database (checked in debugger).
#ResponseBody
#RequestMapping(method = RequestMethod.GET, value = "/{sampleId}/file")
public HttpEntity<byte[]> getFile(#PathVariable Long sampleId) {
ResourceEntity resourceEntity = testSampleRepository.getFile(sampleId);
byte[] content = resourceEntity.getContent();
String fileName = resourceEntity.getFileName();
HttpHeaders header = new HttpHeaders();
header.setContentType(new MediaType("audio", "mpeg"));
header.set(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=" + fileName.replace(" ", "_"));
header.setContentLength(content.length);
return new HttpEntity<byte[]>(content, header);
}
This is how files differ (the left is original one):
Why passing using HTTP distors my file? Should mediaTypes enforce certain encoding? (there was no difference with "audio/mpeg" mediaType and without it).
It should work, if you set the produces = "application/octet-stream" attribute (MediaType.APPLICATION_OCTET_STREAM). Otherwise, you are trapped by Spring's converter framework.
You may want to have a look here, seems your problem is very similar: Spring MVC: How to return image in #ResponseBody? .

Categories