I have implemented REST service for upload multiple files into server.But the problem was that i can not get file details if i use FormDataMultiPart in the REST service.I can get the file content.like wise i tried to get file details like following and it gave me an error saying not supported.
#POST
#Consumes(MediaType.MULTIPART_FORM_DATA)
public void upload(FormDataMultiPart formParams)
{
Map<String, List<FormDataBodyPart>> fieldsByName = formParams.getFields();
//Assume i am sending only files with the request
for (List<FormDataBodyPart> fields : fieldsByName.values())
{
for (FormDataBodyPart field : fields)
{
InputStream is = field.getEntityAs(InputStream.class);
String fileName = field.getName();
field.getMediaType();
//Those work perfectly
//This gave me an error
FormDataContentDisposition f=field.getEntityAs(FormDataContentDisposition .class);
System.out.println(f.getFileName());
}
}
}
Please let me know how can i get files details like type,name,size for each uploaded files if use FormDataMultiPart.
I was able to access file details finally here is the code snippet.
#POST
#Consumes(MediaType.MULTIPART_FORM_DATA)
public void upload(FormDataMultiPart formParams)
{
Map<String, List<FormDataBodyPart>> fieldsByName = formParams.getFields();
//Assume i am sending only files with the request
for (List<FormDataBodyPart> fields : fieldsByName.values())
{
for (FormDataBodyPart field : fields)
{
InputStream is = field.getEntityAs(InputStream.class);
String fileName = field.getName();
field.getMediaType();
//This working fine
FormDataContentDisposition f=field.getFormDataContentDisposition();
System.out.println(f.getFileName());
}
}
}
Related
I have Jersey endpoint that is attempting to create a CSV file and return it via GET; however, all these attempts end up with the same result - the ok status (200) is returned but no file.
#GET
#Path("/research")
#Produces(MediaType.TEXT_PLAIN)
public Response dumpAllResearchAndSupportData() {
QuickDumpBuilderService dumpBuilderService = getQuickDumpService();
List<DevelopmentProposal> researchOtherProposals = dumpBuilderService.getAllResearchRecords();
String csvLocation = dumpBuilderService.buildCSV(researchOtherProposals);
File file = new File(csvLocation);
String filename = "reserach_" + UUID.randomUUID().toString() + ".csv";
return Response.ok(file, MediaType.TEXT_PLAIN).header("Content-Disposition", "attachment; filename=" + filename).build();
}
My CSV file is properly created, but it fails to be returned along with the response.
Notice above, I'm writing the CSV to a temporary location in my tomcat folder and then passing the path to that file back and then attempting to read that from the location here.
Another attempt with the same result where instead of writing the CSV to temp location, I'm just trying to write the ByteArrayOutputStream to the response object.
#GET
#Path("/research")
#Produces(MediaType.APPLICATION_JSON)
public Response dumpAllResearchAndSupportData() {
QuickDumpBuilderService dumpBuilderService = getQuickDumpService();
// Step 1. Retrieve all research and other proposals
List<DevelopmentProposal> researchOtherProposals = dumpBuilderService.getAllResearchRecords();
// Step 2. Create CSV File
ByteArrayOutputStream csvBaos = dumpBuilderService.buildCSV(researchOtherProposals);
// Step 3. Create spreadsheet
ByteArrayOutputStream excelBaos = dumpBuilderService.createExcelSpreadsheet(csvBaos, servlet);
// Step 4. Return spreadsheet
Response.ResponseBuilder response = Response.ok(excelBaos);
return response.build();
Another attempt where I added this "writer" into the response. This attempt generated an error that a "MessageBodyWriter for the ByteArrayStream was not found." That prompted the attempt below.
#GET
#Path("/research")
#Produces(MediaType.TEXT_PLAIN)
public Response dumpAllResearchAndSupportData() {
....
// Step 4. Return spreadsheet
return Response.ok(getOut(csvBaos.toByteArray())).build();
}
private StreamingOutput getOut(final byte[] csvBytes) {
return new StreamingOutput() {
#Override
public void write(OutputStream out) throws IOException, WebApplicationException {
out.write(csvBytes);
out.flush();
}
};
}
I've looked at the following similar answers, and I've attempted all of them with no success.
Not sure what I'm doing wrong - I suspect that it's something to do with how I setup my endpoint and defer to the Java REST API experts here.
File download/save from a Jersey rest api call using ANGULARJS . file is attached with response as "Content-Disposition"
Download CSV file via Rest
jersey - StreamingOutput as Response entity
Thanks for your help.
I need to build a service that can receive 2 binary files (~100k each) and some metadata, preferably in json.
I found this, but it only seems to provide one InputStream to one of the parts. But I'd need two.. so what to do?
You have a few options
Simply add another parameter(s) with a different part annotation
#POST
#Consumes("multipart/form-data")
public Response post(#FormDataParam("file1") InputStream file1,
#FormDaraParam("file2") InputStream file2) {
}
The parts can have the same part name, so you could do
#POST
#Consumes("multipart/form-data")
public Response post(#FormDataParam("file") List<FormDataBodyPart> files) {
for (FormDataBodyPart file: files) {
FormDataContentDisposition fdcd = file.getFormDataContentDisposition();
String fileName = fdcd = getFileName();
InputStream is = file.getValueAs(InputStream.class);
}
}
You could traverse the entire multipart body youself
#POST
#Consumes("multipart/form-data")
public Response post(FormDataMultiPart mulitPart) {
Map<String, List<FormDataBodyPart>> fields = multiPart.getFields();
}
See Also:
Sending multiple files with Jersey: MessageBodyWriter not found for multipart/form-data, for a complete example
File upload along with other object in Jersey restful web service, for how the handle the JSON as a POJO.
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){
I am sending a file via Ajax like this:
// Get the selected files from the input.
var files = fileSelect.files;
// Create a new FormData object.
var formData = new FormData();
// Add the file to the request.
formData.append('photos[]', files[0], files[0].name);
$.ajax({
type:"POST",
url:"URL,
dataType:"json",
headers : {"cache-control":"no-cache"},
timeout : 12000,
processData: false,
data:{
formdata:formData
}
Now I want to work with the send file in my java class, in a ressource like this:
#PermitAll
#POST
#Path(URL)
#Produces(MediaType.APPLICATION_JSON)
public Map<String, Object> fileHandler(#FormParam("formdata") File formdata){ }
But accessing the file does not work, #FormParam("formdata") File formdata seems to be wrong (or more things?). I want to get access to this file in my ressource class somehow. What am I doing wrong? Maybe someone knows a better solution for this.
You can handle it this way:
I have changed the way FormData is passed. Used id of the form and passed it to create form data:
Javacript:
$.ajax({
type : 'POST',
url : rquestURL,
cache:false,
processData:false,
contentType:false,
data : new FormData($("#"+<your_form_id>)[0])}
Rresource (Added #Consumes(MediaType.MULTIPART_FORM_DATA) annotation):
#Path("/upload")
#POST
#Consumes(MediaType.MULTIPART_FORM_DATA)
public ResponseDTO doUpload(FormDataMultiPart multiPartData) {
// non-file fields
final String imageId = multiPartData.getField("<your_field_name>").getValue();
// for file field
final FormDataBodyPart filePart = multiPartData.getField("<file_field_name>");
final ContentDisposition fileDetails = filePart.getContentDisposition();
final InputStream fileInputStream = filePart.getValueAs(InputStream.class);
// use the above fields as required
// file name can be accessed from field "fileDetails"
}
When you deal with files, it's not just FormParam, it's FormDataParam. Also, class File is for entity in your filesystem, not for files inside request. It should be InputStream instead.
So signature should look like this:
#PermitAll
#POST
#Path(URL)
#Produces(MediaType.APPLICATION_JSON)
public Map<String, Object> fileHandler(
#FormDataParam("formdata") InputStream formdata,
#FormDataParam("formdata") FormDataContentDisposition fileDetail
){ }
Here you could also see another parameter "FormDataContentDisposition", from it you could take details about data, like filename and size (would be useful, when you will read InputStream).
Note that I wrote this example for JAX-RS. Not sure what library you use.
I'm using jersey as backend in one of my applications. I am having trouble in uplaoding file using jersey. I have used the common file upload code available on google.
#POST
#Path("/setProfileImage")
#Consumes(MediaType.MULTIPART_FORM_DATA)
#Produces(MediaType.TEXT_HTML)
public String setProfileImage(
#FormDataParam("profileimage") InputStream uploadedInputStream,
#QueryParam("myemail") String myemail) throws IOException {
String contextRoot = uri.getBaseUri().getPath();
String uploadedFileLocationOrig = httpRequest.getSession().getServletContext().getRealPath("") + "/images/" + myemail + "_orig.png";
FileUtils.copyInputStreamToFile(uploadedInputStream, new File(uploadedFileLocationOrig));
return "true";
}
The code runs without error, but the image copied at the destination is not valid and an empty file is returned when I hit this file using its url.
Any ideas what I'm doing wrong here?
I finally figured it out, the version of Jersey was pretty old i.e. 1.17 and following code worked like a charm for me
#POST
#Path("/setProfileImage")
#Consumes(MediaType.MULTIPART_FORM_DATA)
#Produces(MediaType.TEXT_HTML)
public String setProfileImage(
final MimeMultipart file,
#QueryParam("myemail") String myemail) throws IOException, javax.mail.MessagingException {
String uploadedFileLocationOrig = httpRequest.getSession().getServletContext().getRealPath("") + "/images/" + myemail + "_orig.png";
FileUtils.copyInputStreamToFile(file.getBodyPart(0).getInputStream(), new File(uploadedFileLocationOrig));
return "true";
}