Spring mvc When using enctype="multipart/form-data" modelAttribute values equal null in the controller - spring

I use spring mvc I want to uplaod image to jsp form so I add enctype="multipart/form-data" to the form tag but when i add this, modelAttribute values equals null in the controller
This is my form in jsp page:
<form:form action="saveContact" method="post" modelAttribute="Contacting" id="container" enctype="multipart/form-data">
This is the header of the function in controller:
#RequestMapping(value = "/saveContact", method = RequestMethod.POST)
public ModelAndView saveContact(#ModelAttribute ("Contacting") Contacting Contacting,ModelAndView modelndView,HttpServletRequest request ,HttpServletResponse response
) throws Exception {............}
#ModelAttribute ("Contacting") Contacting Contacting all values are null. and When I erease the enctype="multipart/form-data" from form tag its work well but I cant upload the image
this is the uplaud function:
public void uplaodImages(String url,HttpServletRequest request) {
// configures upload settings
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setSizeThreshold(THRESHOLD_SIZE);
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setFileSizeMax(MAX_FILE_SIZE);
upload.setSizeMax(MAX_REQUEST_SIZE);
String uuidValue = "";
FileItem itemFile = null;
try {
// parses the request's content to extract file data
List formItems = upload.parseRequest(request);
Iterator iter = formItems.iterator();
// iterates over form's fields to get UUID Value
while (iter.hasNext()) {
FileItem item = (FileItem) iter.next();
if (item.isFormField()) {
if (item.getFieldName().equalsIgnoreCase(UUID_STRING)) {
uuidValue = item.getString();
}
}
// processes only fields that are not form fields
if (!item.isFormField()) {
itemFile = item;
}
}
if (itemFile != null) {
// get item inputstream to upload file into s3 aws
BasicAWSCredentials awsCredentials = new BasicAWSCredentials(AMAZON_ACCESS_KEY, AMAZON_SECRET_KEY);
AmazonS3 s3client = new AmazonS3Client(awsCredentials);
try {
ObjectMetadata om = new ObjectMetadata();
om.setContentLength(itemFile.getSize());
om.setContentType("image/png");
String ext = FilenameUtils.getExtension(itemFile.getName());
String keyName = uuidValue + '.' + ext;
// s3client.putObject(new PutObjectRequest(S3_BUCKET_NAME,"99/after/img", itemFile,st om));
// s3client.setObjectAcl(S3_BUCKET_NAME, "99/after/img", CannedAccessControlList.PublicRead);
TransferManager tm = new TransferManager(new ProfileCredentialsProvider());
System.out.println("Hello");
// TransferManager processes all transfers asynchronously,
// so this call will return immediately.
Upload upload1 = tm.upload(
S3_BUCKET_NAME, url, itemFile.getInputStream(),om);
System.out.println("Hello2");
try {
// Or you can block and wait for the upload to finish
upload1.waitForCompletion();
System.out.println("Upload complete.");
} catch (AmazonClientException amazonClientException) {
System.out.println("Unable to upload file, upload was aborted.");
amazonClientException.printStackTrace();
}
} catch (AmazonServiceException ase) {
// LOGGER.error(uuidValue + ":error:" + ase.getMessage());
} catch (AmazonClientException ace) {
//LOGGER.error(uuidValue + ":error:" + ace.getMessage());
}
} else {
//LOGGER.error(uuidValue + ":error:" + "No Upload file");
System.out.println("No Upload file");
}
} catch (Exception ex) {
//LOGGER.error(uuidValue + ":" + ":error: " + ex.getMessage());
System.out.println(ex.getMessage());
}
//LOGGER.info(uuidValue + ":Upload done");
System.out.println("Upload done");
}

#RequestMapping(value = "/form.html", method = RequestMethod.POST)
public String handleFormUpload(#RequestParam("name") String name,
#RequestParam("file") MultipartFile file) throws Exception {
}

Related

Return a new thymeleaf page fragment and some file from spring controller

Tell me how to properly implement the spring controller. I want it to return a new thymeleafe page fragment and Excel file at the same time.
I know how to implement a controller to return a page fragment:
#GetMapping("/some_url")
public String updateFragment(Model model) {
model.addAttribute("attribute", someAtribute);
return "some_page :: fragment";
}
And I know how to implement a controller for downloading files:
#GetMapping("some_url")
public void getReport(HttpServletResponse response) throws IOException {
response.setContentType("application/octet-stream");
String headerKey = "Content-Disposition";
String headerValue = "attachment; filename=file.xlsx";
response.setHeader(headerKey, headerValue);
try {
FileInputStream inputStream = new FileInputStream(new File("path_to_file"));
Workbook workbook = WorkbookFactory.create(inputStream);
Sheet sheet = workbook.getSheetAt(0);
int row = 12;
Row exampleRow = sheet.getRow(12);
int count = 1;
for (SIZForKomplex s : objectList) {
if (s.getNumber() != 0) {
sheet.getRow(row).setRowStyle(exampleRow.getRowStyle());
sheet.getRow(row).setHeight(exampleRow.getHeight());
for (int i = 0; i < 8; i++) {
sheet.getRow(row).getCell(i).setCellStyle(exampleRow.getCell(i).getCellStyle());
}
sheet.getRow(row).getCell(0).setCellValue(count);
sheet.getRow(row).getCell(1).setCellValue(s.getNomenclatureNumber());
sheet.getRow(row).getCell(2).setCellValue(s.getNamesiz());
sheet.getRow(row).getCell(3).setCellValue(s.getSize());
sheet.getRow(row).getCell(4).setCellValue(s.getHeight());
sheet.getRow(row).getCell(5).setCellValue(s.getNumber());
sheet.getRow(row).getCell(6).setCellValue(sizRepository.findById(s.getId()).orElseThrow().getEd_izm());
sheet.getRow(row).getCell(7).setCellValue(" ");
row++;
count++;
}
}
inputStream.close();
ServletOutputStream outputStream = response.getOutputStream();
workbook.write(outputStream);
workbook.close();
outputStream.close();
} catch (IOException | EncryptedDocumentException
ex) {
ex.printStackTrace();
}
}
But how do I combine this. I need to update the data on the page and download the Excel file

Vuetify + Spring: How do I upload and display images correctly?

I've done uploading and displaying images with Vuetify and Spring.
It's work, but I'm not sure that I did it correctly. I am not sure that I have implemented the correct approach to solving this problem. Can you check it and say what you think?
On side Vuetify I use v-file-input component and axios for sending image to the server:
<v-file-input
v-model="selectedLogo"
accept="image/png, image/jpeg, image/bmp"
placeholder="Выберите Логотип"
prepend-icon="mdi-camera"
label="Логотип"
show-size
>
<template v-slot:append-outer>
<v-btn small #click="uploadLogo">
<v-icon dense>mdi-upload</v-icon>
</v-btn>
</template>
</v-file-input>
//...
uploadLogo(){
uploadLogo(this.$axios, this.company.id, this.selectedLogo)
}
//...
export const uploadLogo = function ($axios, id, logo) {
let formData = new FormData()
formData.append("logo", logo)
return $axios.post(url+ `/${id}/logo`,
formData,
{
headers: {
'Content-Type': 'multipart/form-data'
}
})
}
In Spring I have RestController:
#RestController
#RequestMapping("/api/")
public class FileController {
#Autowired
private FileStorageService fileStorageService;
#PostMapping("companies/{id}/logo")
public ResponseEntity<Object> uploadFile(#PathVariable Long id, #RequestParam("logo") MultipartFile logo) {
String fileName = fileStorageService.uploadLogo(id, logo);
return new ResponseEntity<>(HttpStatus.OK);
}
#GetMapping("/companies/{id}/logo")
public ResponseEntity<Resource> downloadLogo(#PathVariable Long id, HttpServletRequest request) {
Resource resource = fileStorageService.loadLogoAsResource(id);
String contentType = null;
try {
contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath());
} catch (IOException ex) {
contentType = "application/octet-stream";
}
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType(contentType))
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
.body(resource);
}
}
fileStorageService:
#Service
public class FileStorageService {
private final Path logoStorageLocation;
#Autowired
public FileStorageService(FileStorageProperties fileStorageProperties) {
this.logoStorageLocation = Paths.get(fileStorageProperties.getLogoDir())
.toAbsolutePath().normalize();
try {
Files.createDirectories(this.logoStorageLocation);
} catch (Exception ex) {
throw new FileStorageException("Could not create the directory where the uploaded files will be stored.", ex);
}
}
public String uploadLogo(Long id, MultipartFile file) {
String fileExtension = StringUtils.getFilenameExtension(file.getOriginalFilename());
String fileName = id.toString() + "." + fileExtension;
try {
if(fileName.contains("..")) {
throw new FileStorageException("Sorry! Filename contains invalid path sequence " + fileName);
}
Path targetLocation = this.logoStorageLocation.resolve(fileName);
Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
return fileName;
} catch (IOException ex) {
throw new FileStorageException("Could not store file " + fileName + ". Please try again!", ex);
}
}
public Resource loadLogoAsResource(Long id) {
String fileName = id.toString() + ".png";
try {
Path filePath = this.logoStorageLocation.resolve(fileName).normalize();
Resource resource = new UrlResource(filePath.toUri());
if(resource.exists()) {
return resource;
} else {
throw new FileNotFoundException("File not found " + fileName);
}
} catch (MalformedURLException ex) {
throw new FileNotFoundException("File not found " + fileName, ex);
}
}
}
My idea is uploading/displaying images by URL http://server/api/companies/{id}/logo without knowing the name of the logo file.
For displaying I use v-img component:
<v-img :src="'http://localhost:8081/api/companies/' + company.id +'/logo'"></v-img>
Questions:
What do you think about my solution?
Here I use RestController for displaying images.
I thought that I can get image directly by its location on the server. Without using RestController for #GetMapping. For example, if my images are stored in the folder with path /images/companies/logo on the server, I can get my images by URL with path http://server/images/companies/logo/namelogo.png
In this way, I should know name of the file on the server.
How can I display the image without using RestController for #GetMapping?

Receive data and file in method POST

I have a WebService that is working and receiving files using the POST method, but in which I also need to receive data, simultaneously.
ASP.NET WebApi code:
public Task<HttpResponseMessage> Post()
{
HttpRequestMessage request = this.Request;
if (!request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string root = System.Web.HttpContext.Current.Server.MapPath("~/App_Data/uploads");
var provider = new MultipartFormDataStreamProvider(root);
var task = request.Content.ReadAsMultipartAsync(provider).
ContinueWith<HttpResponseMessage>(o =>
{
string file1 = provider.FileData.First().LocalFileName;
return new HttpResponseMessage()
{
Content = new StringContent("File uploaded.")
};
}
);
return task;
}
And the client, developed for Android, is sending the file and the data like this (the send of the file is tested and working, the sending of the data is still not tested, as I need it to be working in the server side):
OkHttpClient client = new OkHttpClient();
RequestBody requestBody = new MultipartBuilder()
.type(MultipartBuilder.FORM)
.addPart(
Headers.of("Content-Disposition", "form-data; name=\"title\""),
RequestBody.create(null, "Sample Text Content"))
.addPart(
Headers.of("Content-Disposition", "form-data; name=\"file\"; filename=\"" + fileName + ".png\""),
RequestBody.create(MEDIA_TYPE_PNG, bitmapdata))
.addFormDataPart("fullpath", "test")
.build();
final com.squareup.okhttp.Request request = new com.squareup.okhttp.Request.Builder()
.url(url)
.post(requestBody)
.build();
How can I change the server to read not only the file but also the data?
Can any one help?
Thanks in advance.
The client in this case android is sending additional values in the body like media_type_png. I had to do something similar however the client was angular and not a mobile app, after some searching back then I found code from the following stackoverflow. Which resulted in the code below.
First receive the incoming message and check that you can process it i.e. [IsMimeMultipartContent][1]()
[HttpPost]
public async Task<HttpResponseMessage> Upload()
{
// Here we just check if we can support this
if (!Request.Content.IsMimeMultipartContent())
{
this.Request.CreateResponse(HttpStatusCode.UnsupportedMediaType);
}
// This is where we unpack the values
var provider = new MultipartFormDataMemoryStreamProvider();
var result = await Request.Content.ReadAsMultipartAsync(provider);
// From the form data we can extract any additional information Here the DTO is any object you want to define
AttachmentInformationDto attachmentInformation = (AttachmentInformationDto)GetFormData(result);
// For each file uploaded
foreach (KeyValuePair<string, Stream> file in provider.FileStreams)
{
string fileName = file.Key;
// Read the data from the file
byte[] data = ReadFully(file.Value);
// Save the file or do something with it
}
}
I used this to unpack the data:
// Extracts Request FormatData as a strongly typed model
private object GetFormData(MultipartFormDataMemoryStreamProvider result)
{
if (result.FormData.HasKeys())
{
// Here you can read the keys sent in ie
result.FormData["your key"]
AttachmentInformationDto data = AttachmentInformationDto();
data.ContentType = Uri.UnescapeDataString(result.FormData["ContentType"]); // Additional Keys
data.Description = Uri.UnescapeDataString(result.FormData["Description"]); // Another example
data.Name = Uri.UnescapeDataString(result.FormData["Name"]); // Another example
if (result.FormData["attType"] != null)
{
data.AttachmentType = Uri.UnescapeDataString(result.FormData["attType"]);
}
return data;
}
return null;
}
The MultipartFormDataMemoryStreamProvider is defined as follows:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.Web;
namespace YOURNAMESPACE
{
public class MultipartFormDataMemoryStreamProvider : MultipartMemoryStreamProvider
{
private readonly Collection<bool> _isFormData = new Collection<bool>();
private readonly NameValueCollection _formData = new NameValueCollection(StringComparer.OrdinalIgnoreCase);
private readonly Dictionary<string, Stream> _fileStreams = new Dictionary<string, Stream>();
public NameValueCollection FormData
{
get { return _formData; }
}
public Dictionary<string, Stream> FileStreams
{
get { return _fileStreams; }
}
public override Stream GetStream(HttpContent parent, HttpContentHeaders headers)
{
if (parent == null)
{
throw new ArgumentNullException("parent");
}
if (headers == null)
{
throw new ArgumentNullException("headers");
}
var contentDisposition = headers.ContentDisposition;
if (contentDisposition == null)
{
throw new InvalidOperationException("Did not find required 'Content-Disposition' header field in MIME multipart body part.");
}
_isFormData.Add(String.IsNullOrEmpty(contentDisposition.FileName));
return base.GetStream(parent, headers);
}
public override async Task ExecutePostProcessingAsync()
{
for (var index = 0; index < Contents.Count; index++)
{
HttpContent formContent = Contents[index];
if (_isFormData[index])
{
// Field
string formFieldName = UnquoteToken(formContent.Headers.ContentDisposition.Name) ?? string.Empty;
string formFieldValue = await formContent.ReadAsStringAsync();
FormData.Add(formFieldName, formFieldValue);
}
else
{
// File
string fileName = UnquoteToken(formContent.Headers.ContentDisposition.FileName);
Stream stream = await formContent.ReadAsStreamAsync();
FileStreams.Add(fileName, stream);
}
}
}
private static string UnquoteToken(string token)
{
if (string.IsNullOrWhiteSpace(token))
{
return token;
}
if (token.StartsWith("\"", StringComparison.Ordinal) && token.EndsWith("\"", StringComparison.Ordinal) && token.Length > 1)
{
return token.Substring(1, token.Length - 2);
}
return token;
}
}
}

File upload in Spring

I am trying to upload an audio file using the following code on server.Right now, it works perfectly well for image files but not for audios.I think MultipartFile should work with audio files as well.Can any one tell me what is wrong here?
I am getting "The server refused this request because the request entity is in a format not supported by the requested resource for the requested method." error.
Does MultipartFile not work with audio files?If no what is an alternative?
#Transactional
public BaseVO uploadImage(MultipartFile file, long userId){
Map<String, Object> alertParams = new HashMap<String, Object>();
try{
if (!file.isEmpty()) {
Image profileImage = imageRepository.findByUserId(userId);
if(profileImage == null){
profileImage = new Image();
profileImage.setUserId(userId);
}
File dir = null;
String realPath;
if(liveBuild == "true"){
realPath = liveImageUploadRepository;
dir = new File(realPath);
}else{
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
realPath = request.getSession().getServletContext().getRealPath("/") + devImageUploadRepository;
dir = new File(realPath);
}
if (!dir.exists()) {
dir.mkdirs();
}
String finalFileStorePath = realPath + "/" + userId + ".jpg";
File path = new File(finalFileStorePath);
file.transferTo(path);
profileImage.setImagePath(realPath);
//profileImage.setImageName(userId + ".jpg");
profileImage.setImageName(userId+"");
profileImage.setImageType(".jpg");
imageRepository.save(profileImage);
alertParams.put("id", profileImage.getId());
} else {
return new BaseVO(alertParams, Constants.STATUS_OK, Constants.STATUS_OK_MSG);
}
}catch(HibernateException e){
return new BaseVO(alertParams, Constants.STATUS_ERROR, Constants.STATUS_ERROR_MSG + " " + e.getMessage());
} catch (IllegalStateException e) {
e.printStackTrace();
return new BaseVO(alertParams, Constants.STATUS_ERROR, Constants.STATUS_ERROR_MSG);
} catch (IOException e) {
e.printStackTrace();
return new BaseVO(alertParams, Constants.STATUS_ERROR, Constants.STATUS_ERROR_MSG);
}
return new BaseVO(alertParams, Constants.STATUS_OK, Constants.STATUS_OK_MSG);
}

Birt Report not opening in PDF

Hello guys
I am sending my form values to controller and controller to rptdesign file my it is generating the report in temp folder with proper value but my requirement is that it should user to save or open dialog so that user can save the report or open
i think ajax request will not allow to download any file so if some one know to better solution plz reply
my controller is below
#RequestMapping("/leave/generateEmpLeaveReport.json")
public void generateEmployeeLeaveReport(HttpServletRequest request,
HttpServletResponse response) throws Exception {
String reportName = "D:/git-repositories/cougar_leave/src/java/com//report/myLeaveSummary.rptdesign";
File designTemplateFile = new File(reportName);
if (!designTemplateFile.exists()) {
throw new FileNotFoundException(reportName);
}
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("empId", NumberUtils.toInt(request.getParameter("id")));
parameters.put("reportTitle", "EMPLOYEE LEAVE");
parameters.put("fromDate", request.getParameter("fromDate"));
parameters.put("toDate", request.getParameter("toDate"));
parameters.put("leaveType",
NumberUtils.toInt(request.getParameter("leaveType")));
parameters.put("transactionType",
NumberUtils.toInt(request.getParameter("transactionType")));
reportManager.addSystemParams(parameters, null,
RequestUtils.getUser(request));
File file = null;
try {
ReportType reportType = ReportType.PDF;
OfflineReportContext reportContext = new OfflineReportContext(
reportName, reportType, parameters, null,
"EMPLOYEE LEAVE SUMMARY");
StringBuffer buffer = new StringBuffer();
file = offlineReportGenerator.generateReportFile(reportContext,
buffer);
ControllerUtils
.openFile(file.getParent(), response, file.getName());
} catch (Exception e) {
log.error(e, e);
} finally {
if (file != null && file.exists()) {
file.canExecute();
}
}
}
my ajax request is below
generateReport : function() {
if (this.form.valid()) {
fromDate = new Date($("input[name='fromDate']").val())
toDate = new Date($("input[name='toDate']").val())
if (fromDate > toDate) {
GtsJQuery
.showError("To date should be greater or equals than From date !")
} else {
var request = GtsJQuery.ajax3(GtsJQuery.getContextPath()
+ '/leave/generateEmpLeaveReport.json', {
data : {
id : $("input[name='employeeId']").val(),
fromDate : $("input[name='fromDate']")
.val(),
toDate : $("input[name='toDate']").val(),
leaveType : $("select[name='leaveType']")
.val(),
transactionType : $("select[name='transactionType']")
.val(),
orderBy : $("select[name='orderBy']").val()
}
});
request.success(this.callback("onSubscribeSuccess"))
}
}
},
The controller response should be the temp file itself, just adjust the content-type.

Resources