How to generate file chooser in Swagger-ui for body inpustream - java

Hello i have the following jaxrs entry
#PUT()
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_OCTET_STREAM)
#ApiOperation(value = "Bla bla.")
#Path("secure/flappy")
public Response testput(
#ApiParam(value = "pwet",type = "file",format = "binary", required = true) InputStream certificate) throws Throwable {
try (InputStream stream = certificate) {
//Consume stream
return Response.ok().build();
}
}
And the generated swagger-ui page for this entry
I would like to know how to document my paremeter for getting only one parameter presented as a file chooser in swagger-ui.

#sdc: You're right i had to use multi part form data for getting a working file chooser in Swagger-ui. I also had to use #ApiImplicitParam for getting it working.
#PUT()
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.MULTIPART_FORM_DATA)
#ApiOperation(value = "Bla bla.")
#Path("secure/flappy")
#ApiImplicitParams({
#ApiImplicitParam(name = "file", value = "bla bla.", required = true, dataType = "java.io.File", paramType = "form")
})
public Response testput(#ApiParam(hidden = true) #FormDataParam("file") final InputStream certificate
) throws Throwable {
//TODO do something
return Response.ok().build();
}

I am not very familiar with Swagger UI, but this thread might be helpful
https://github.com/swagger-api/swagger-ui/issues/72
I see an example using an#ApiParam annotation
and this post talks about a file upload with the
def uploadFile annotation
https://github.com/swagger-api/swagger-ui/issues/169
#PUT
#Path("/secure/flappy")
#Consumes(Array(MediaType.MULTIPART_FORM_DATA))
#ApiOperation(value = "test a put file upload")
def uploadFile(
#ApiParam(value = "file to upload", required=false) #FormDataParam("file") inputStream: InputStream,
#ApiParam(value = "file detail") #FormDataParam("file") fileDetail: FormDataContentDisposition) = {
val uploadedFileLocation = "./" + fileDetail.getFileName
IOUtils.copy(inputStream, new FileOutputStream(uploadedFileLocation))
val msg = "File uploaded to " + uploadedFileLocation + ", " + (new java.io.File(uploadedFileLocation)).length + " bytes"
val output = new com.wordnik.swagger.sample.model.ApiResponse(200, msg)
Response.status(200).entity(output).build()
}

I suppose you need to use in the parameter description following:
#RequestPart("file") MultipartFile file
At least for me it gives a swagger form with a file selection button.
The solution was found in the examples here:
https://github.com/springfox/springfox-demos

Related

Swagger documentation: description of the content of the response

I have a simple fileUpload rest API which stores the uploaded file in database and returns with the unuque reference of the uploaded file in the database (uuid).
I use swagger to generate API documentation and it works like a charm but I can not find a way to add description text to describe the content of the response.
This is the signature of my REST:
#POST
#Path("/upload")
#Consumes(ExtendedMediaType.MULTIPART_FORM_DATA)
#ApiOperation(
value = "Save an image",
notes = "Save the uploaded image to database.",
response = String.class)
#ApiResponses(value = {
#ApiResponse(code = 200, message = "The uploaded image has been saved.", response = String.class),
#ApiResponse(code = 500, message = "Error while trying to resize the image.<p>Internal error code: 2103", response = a.b.ErrorInfo.class)})
#Override
public String uploadImage(
#ApiParam(value = "file to upload", required = true) #FormDataParam("file") final InputStream inputStream,
#ApiParam(value = "details of the uploaded file", required = true) #FormDataParam("file") final FormDataContentDisposition fileDetail) {
//return UUID.randomUUID().toString();
}
I would like to add the following info to the API documentation in order to describe the content of the response string:
"The unique id of the uploaded image."
I have checked the ApiResponses documentation but I have not found anything related to this topic.
I can put this info next to the ApiResponse HTTP 200 but I am not sure whether this solution is correct or not.
From my experience with swagger, I think it must be specified in the notes field in the ApiOperation like below
#ApiOperation(
value = "Save an image",
notes = "Returns the unique id of the uploaded image",
response = String.class)

Upload file to Jersey web services with spring MultipartFile

I have a 3 step process to upload a file on a server:
Using EXT.JS form, I upload a file to a controler.
In the controler, the method gets the MultipartFile, builds a rest call using rest template and send it to the server.
On the server, the specified method should receive the multipart data and process the file.
Here is the method at the step 2 that get the file from the UI side (EXT.JS):
#RequestMapping("/customerUploadFile/upload")
#ResponseBody
public JsonResponse uploadFile(CustomerUploadBean bean,
#RequestParam("filePath") MultipartFile filePath) throws IOException {
long fileSize = filePath.getSize();
HttpEntity<CustomerUploadBean> httpEntity = getHttpEntity(bean);
byte[] byteArr = filePath.getBytes();
MultiValueMap<String, Object> parameters = new LinkedMultiValueMap<String, Object>();
parameters.add("userId", httpEntity.getHeaders().get("userId"));
parameters.add("file", byteArr);
// to set content type of header
org.springframework.http.HttpHeaders headers = new org.springframework.http.HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<JsonResponse> jsonResponse = restTemplate.exchange(uri, HttpMethod.POST,
new HttpEntity<MultiValueMap<String, Object>>(parameters, headers),
new ParameterizedTypeReference<JsonResponse>() {
});
JsonResponse response = jsonResponse.getBody();
if (jsonResponse.getStatusCode() == HttpStatus.OK) {
response.setSuccess(true);
} else {
response.setSuccess(false);
}
return response;
}
I've verified, the filePath object have the file and contains information about the file.
At the step 3, here is the method in the controller on the server that awaits for the file to process it:
public Response importUserProfileCSV(
#ApiParam(value = "Service Name", required = true) #PathParam("service") String service,
#ApiParam(value = "CSV file to upload.", required = true) #FormDataParam("file") InputStream uploadedInputStream,
#ApiParam(value = "CSV file detail", required = true) #FormDataParam("file") FormDataContentDisposition fileDetail) {
return delegate.importUserProfileCSV(uploadedInputStream, fileDetail,
service, "user");
}
The problem here is that at the step 3, in the method right above, the fileDetail object contains only null values... How can I adapt the method of step 2 (spring framework) to the method of step 3 (jersey).

Java Swagger (Springfox) annotations for streaming multipart file upload

We are using spring controllers to handle file uploads:
For example:
#RequestMapping(value = "/scan", method = RequestMethod.POST, consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
public ScanResult scan(HttpServletRequest request) throws IOException, FileUploadException {
return scanService.scanFile(parseMultipart(request));
}
But we are not using any multipart resolver, we are streaming the files from the servlet request input stream. We need to start processing the file immediately for performance reasons.
When doing this this way, we can't seem to use the typical detection/configuration for multipart files. I know Springfox (which we use to generate our swagger docs) will generate the appropriate swagger controls if it sees a MultipartFile as a controller parameter, which will not be the case for us.
Are there any other config options available to hint to springfox that we want a file upload here?
Regarding breaking changes in Springfox v2.7.0:
You need to use dataType = "__file" instead of file as commented in https://github.com/springfox/springfox/issues/1285
Found my answer here: https://github.com/springfox/springfox/issues/1285
The following implicit params give me what I need:
#ApiImplicitParams (value = {
#ApiImplicitParam(dataType = "file", name = "file", required = true,paramType = "form")}
#RequestMapping(value = "/scan", method = RequestMethod.POST, consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
public ScanResult scan(HttpServletRequest request) throws IOException, FileUploadException {
return scanService.scanFile(parseMultipart(request));
}
This adds a simple file picker to the API. To make things more confusing, turns out this functionality was broken in Springfox 2.4 - the version I was using. Adding that annotation and updating versions was all I needed to do.
That's right
https://stackoverflow.com/a/44385675/3810914
In Controller It should be:
#ApiOperation(value = "Upload file", response = String.class)
#ApiResponses({
#ApiResponse(code = 500, message = "Internal Server Error"),
#ApiResponse(code = 400, message = "Bad request")
})
#ApiImplicitParams (value = {
#ApiImplicitParam(dataType = "__file", name = "fileData", required = true,paramType = "form")})
#PostMapping(value = "/upload", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
public ResponseEntity<?> uploadFileSimple(UploadFile form) {
// Create folder to save file if not exist
File uploadDir = new File(UPLOAD_DIR);
if (!uploadDir.exists()) {
uploadDir.mkdirs();
}
MultipartFile fileData = form.getFileData();
String name = fileData.getOriginalFilename();
if (name != null && name.length() > 0) {
try {
// Create file
File serverFile = new File(UPLOAD_DIR + "/" + name);
BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(serverFile));
stream.write(fileData.getBytes());
stream.close();
return ResponseEntity.ok("/file/" + name);
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error when uploading");
}
}
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Bad request");
}
And In Model:
package com.xxx.xxx.request;
import lombok.*;
import org.springframework.web.multipart.MultipartFile;
#Setter
#Getter
#NoArgsConstructor
#AllArgsConstructor
public class UploadFile {
private MultipartFile fileData;
}

Trying to pass Json object to Jersey restfull service as FormDataParam

I do not know how to pass Java object to Jersey restfull service as FormDataParam. The service works perfectly with curl, but Swagger responds with error. The problem is most probably with annotation #FormDataParam. Swagger does not throw 415 Error Unsupported Media File, but it
Here is the code Jersey service:
#POST
#ApiOperation(value = "Upload", notes = "", response = ImageAPIResponse.class)
#Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, "application/x-javascript" })
#Consumes(MediaType.MULTIPART_FORM_DATA)
#ApiResponses(value = {
#ApiResponse(code = 200, message = "Successful or application error (see notes)", response = ImageAPIResponse.class) })
public ImageAPIUploadUpdateResponse upload(
#ApiParam(required = true, value = "user name part of credentials") #FormDataParam("user_name") String userName, //
#ApiParam(required = true, value = "") #FormDataParam("file") File file, //
#ApiParam(required = true, value = "") #FormDataParam("file") FormDataContentDisposition contentDispositionHeader,
#ApiParam(required = false, value = "") #FormDataParam("file_name") String fileName,
#ApiParam(required = false, value = "") #FormDataParam("meta_data") ImageMetaData metaData) {
ImageAPIResponse imageAPIResponse = new ImageAPIResponse();
//metaData object keeps being null...
return imageAPIResponse;
}
public class ImageMetaData{
public String fileName;
public String fileType;
}
Did anyone encounter a similar problem with FormDataParam? It would be great if I could use this Jersey annotation in my parameters.

Rest service Java for file upload and JSON data

Can I have a rest service that can be used for file upload i.e. multi-part form data and JSON parameter? Below is the example of the service.
#POST
#Path("/upload")
#Consumes({ MediaType.MULTIPART_FORM_DATA, MediaType.APPLICATION_JSON })
public Response uploadFile(#FormDataParam("file") InputStream uploadedInputStream,#FormDataParam("file") FormDataContentDisposition fileDetail, City city){
The problem is while testing I am trying to pass both file as an attachment and city object as JSON, it is giving me error as Content-Type could either be application/json or multipart/form-data.
Let me know if there is any way to handle this
You may Use Any Client Side Language to submit form with MultipartFile and Json data. I am writing Java Code in Spring MVC here. It will send String Json and MultiPartFile. then Me going to to Cast String JSON to Map, and Save File at Desired Location.
#RequestMapping(value="/hotel-save-update", method=RequestMethod.POST )
public #ResponseBody Map<String,Object> postFile(#RequestParam(value="file", required = false) MultipartFile file,
#RequestParam(value = "data") String object ){
Map<String,Object> map = new HashMap<String, Object>();
try {
ObjectMapper mapper = new ObjectMapper();
map = mapper.readValue(object, new TypeReference<Map<String, String>>(){});
}catch (Exception ex){
ex.printStackTrace();
}
String fileName = null;
if (file != null && !file.isEmpty()) {
try {
fileName = file.getOriginalFilename();
FileCopyUtils.copy(file.getBytes(), new FileOutputStream(servletContext.getRealPath("/resources/assets/images/hotelImages") + "/" + fileName));
} catch (Exception e) {
header.put(Utils.MESSAGE, "Image not uploaded! Exception occured!");
return result;
}
}
}
Can't you leave the #Consumes off and check the Content-Type header in the method itself, deciding what to do in code?
Your problem seems to be a restriction in the functionality of that annotation (is it Spring MVC?)
I have solved my problem by passing JSON as String from client and then converting String to JSON object.
#POST
#Path("/upload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(#FormDataParam("file") InputStream uploadedInputStream,
#FormDataParam("file") FormDataContentDisposition fileDetail, #FormDataParam("city") String city){

Categories

Resources