I'm trying to upload files, but the Multipartfiles are not getting passed on properly.
Here is my controller where I'm trying to add some files. Only the #RequestParam gets returned, Arrays.asList(files) returns an empty array. I'll add the result of the print lines below.
#Transactional
#RequestMapping(path = "/profile/files", method=RequestMethod.POST)
#ApiResponses(value = {
#ApiResponse(code = HttpServletResponse.SC_BAD_REQUEST, message = "Wrong file type", response = ErrorResponse.class),
#ApiResponse(code = HttpServletResponse.SC_FORBIDDEN, message = "Not authorized", response = ErrorResponse.class),
#ApiResponse(code = HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message = "Internal Error", response = InternalErrorResponse.class)
})
#ResponseBody
#ApiOperation(
value = "Add files",
tags = "Users"
)
public List<FileDto> addProfilePicture(#RequestParam("file") MultipartFile[] files) {
System.out.println("Controller: Files from params: " + files.toString());
List<MultipartFile> filesToAdd = Arrays.asList(files);
System.out.println("Controller: Files Array.asList: " + filesToAdd);
List<File> savedFiles = userService.addFiles(filesToAdd);
System.out.println("Controller: Files returned from addFiles(): " + savedFiles);
return savedFiles.stream().map(FileDto::new).collect(Collectors.toList());
}
This is the service part:
public List<File> addFiles(List<MultipartFile> files) {
System.out.println("Service: Input files: " + files);
List<File> savedFiles = new ArrayList<>();
for(MultipartFile file: files){
File savedFile = fileService.save(file, FileService.LOCATION_DOCUMENT_FILE, S3Adapter.ACL_OWNER_ONLY);
savedFiles.add(savedFile);
}
System.out.println("Service: Saved files: " + savedFiles);
return savedFiles;
}
This is what the print lines are producing for me when trying to upload images through Postman:
Controller: Files from params: [Lorg.springframework.web.multipart.MultipartFile;#794108b7
Controller: Files Array.asList: []
Service: Input files: []
Service: Saved files: []
Controller: Files returned from addFiles(): []
Looks like while you are uploading from POSTMAN, you are using binary option. This option only works if you are receiving as HttpServletRequest / MultipartRequest.
To receive the files as #RequestParam("files") you need to use form-data option and give the key as files and for value choose file from the dropdown, choose multiple files and submit the request. It will work fine.
Related
I have a method that upload files, i want to accept just (pdf) and (docx) files, how i can do that.
this is the method :
#PostMapping("/upload")
public ResponseEntity<ResponseMessage> uploadFile (#RequestParam("file") MultipartFile file){
String message = "";
try {
fileService.store(file);
message = "Uploaded the file successfully: " + file.getOriginalFilename();
return ResponseEntity.status(HttpStatus.OK).body(new ResponseMessage(message));
} catch (Exception e) {
message = "Could not upload the file: " + file.getOriginalFilename() + "!";
return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body(new ResponseMessage(message));
}
}
You can set allowed content type for endpoint:
#PostMapping("/upload", consumes = {MediaType.APPLICATION_PDF_VALUE, "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"})
Or you can validate file extension from input.
Other solution is to validate file extension from input as suggested by #Kryszak.
Simply add one if condition to allow pdf and docx.
For Example :
if (StringUtils.endsWithIgnoreCase(fileName, "pdf") || StringUtils.endsWithIgnoreCase(fileName, "docx")){
//process file
}
else{
// show message to user, only accept pdf & docx files.
}
Currently I use the below code to post single file using RestAssured.
RestAssured.given().contentType(ContentType.MULTIPART_FORM_DATA.toString()).request().multiPart("files", ScreenshotFile).post().then().statusCode(200);
However I want to upload multiple files from the below mentioned FileList.
File ScreenShotFolder = new File("C:\\Users\\1451615\\Desktop\\SessionScreenshot\\");
File ScreenShotFiles[] = ScreenShotFolder.listFiles();
I have put a for loop to post multiple files in the same request. Please find below the code for same.
File ScreenShotFolder = new File("C:\\Users\\1451615\\Desktop\\SessionScreenshot\\");
File ScreenShotFiles[] = ScreenShotFolder.listFiles();
RestAssured.baseURI = "http://10.141.188.112:7080/PIMSelfService/testing/uploadResultImg";
RequestSpecification request = RestAssured.given().contentType(ContentType.MULTIPART_FORM_DATA.toString()).request();
for (File file: ScreenShotFiles) {
System.out.println("File name: " + file.getName());
String FilePath = file.getAbsolutePath();
File ScreenShotPath = new File(FilePath);
System.out.println(ScreenShotPath);
request.multiPart("files", ScreenShotPath);
}
request.post().then().statusCode(200);
ValidatableResponse createAttachemnetResponse = expect()
.given()
.spec(requestSpecification)
.header("content-type", "multipart/form-data")
.multiPart("files-0", new File("testImages/1.jpg"))
.multiPart("files-1", new File("testImages/2.png"))
.multiPart("files-2", new File("testImages/3.png"))
.multiPart("files-3", new File("testImages/4.png"))
.multiPart("files-4", new File("testImages/5.png"))
.formParams("txn_id", transactionId)
.when()
.post(TRANSACTION_BASEPATH + POST_ATTACHMENT)
.then()
.spec(responseSpecification);
My program makes use of a library to upload a file located in an Azure File Share to Sharepoint, after which the file is deleted from Azure File Share. Below is a small (the relevant) part of my code; when I run it the file is uploaded correctly, but isn't removed afterwards isn't removed because it is still in use by an SMB client (it's "marked for deletion", but is only deleted once the Azure Function is disabled).
My guess was that since an InputStream is opened in the wrapper.uploadFile, but not closed that might be it, but resource.isOpen() always returns false
main.class
File file = new File (filepath);
Resource resource = new FileSystemResource(filepath);
PLGSharepointClient wrapper = new PLGSharepointClient(user, passwd, domain, spSiteUrl);
JSONObject jsonMetadata = new JSONObject();
wrapper.uploadFile(spFolder, resource, jsonMetadata);
resource.getInputStream().close();
System.out.println(resource.isOpen());
file.delete();
wrapper.uploadFile
public JSONObject uploadFile(String folder, Resource resource, JSONObject jsonMetadata) throws Exception {
LOG.debug("Uploading file {} to folder {}", resource.getFilename(), folder);
JSONObject submeta = new JSONObject();
submeta.put("type", "SP.ListItem");
jsonMetadata.put("__metadata", submeta);
headers = headerHelper.getPostHeaders("");
headers.remove("Content-Length");
byte[] resBytes = IOUtils.readFully(resource.getInputStream(), (int) resource.contentLength());
RequestEntity<byte[]> requestEntity = new RequestEntity<>(resBytes,
headers, HttpMethod.POST,
this.tokenHelper.getSharepointSiteUrl(
"/_api/web/GetFolderByServerRelativeUrl('" + UriUtils.encodeQuery(folder, StandardCharsets.UTF_8) +"')/Files/add(url='"
+ UriUtils.encodeQuery(resource.getFilename(), StandardCharsets.UTF_8) + "',overwrite=true)"
)
);
ResponseEntity<String> responseEntity =
restTemplate.exchange(requestEntity, String.class);
String fileInfoStr = responseEntity.getBody();
LOG.debug("Retrieved response from server with json");
JSONObject jsonFileInfo = new JSONObject(fileInfoStr);
String serverRelFileUrl = jsonFileInfo.getJSONObject("d").getString("ServerRelativeUrl");
LOG.debug("File uploaded to URI", serverRelFileUrl);
String metadata = jsonMetadata.toString();
headers = headerHelper.getUpdateHeaders(metadata);
LOG.debug("Updating file adding metadata {}", jsonMetadata);
RequestEntity<String> requestEntity1 = new RequestEntity<>(metadata,
headers, HttpMethod.POST,
this.tokenHelper.getSharepointSiteUrl("/_api/web/GetFileByServerRelativeUrl('" + UriUtils.encodeQuery(serverRelFileUrl, StandardCharsets.UTF_8) + "')/listitemallfields")
);
ResponseEntity<String> responseEntity1 =
restTemplate.exchange(requestEntity1, String.class);
LOG.debug("Updated file metadata Status {}", responseEntity1.getStatusCode());
return jsonFileInfo;
}
In your wrapper.upload file, add resource.getInputStream().close() and check if this works.
I have a web form that I'm trying to add multi-file upload to. Currently, I can select a folder and upload multiple files. I have a Spring controller which gets the List<MultipartFile> containing all the files, resucively. However, the "original file name" includes JUST the file name. What I want is the relative path from the selected root folder, and the file name.
For example, if user uploads a directory C:\MyStuff\mypics\, I'd want to see "dog\dog1.jpg", "cat\cat5.jpg", etc. Or, "mypics\dog\dog1.jpg" would be acceptable.
HTML:
<button ngf-select="myController.uploadTest($files)"
multiple="multiple" webkitdirectory accept="image/*">Select Files ngf</button>
AngularjS Controller:
// for multiple files:
myController.uploadFiles = function (files) {
console.log("uploading files: " + files.length);
if (files && files.length) {
// send them all together for HTML5 browsers:
Upload.upload({
url: 'load-service/upload-test',
data: {file: files, myVal1: 'aaaa'},
// setting arraykey here force the data to be sent as the same key
// and resolved as a List<> in Spring Controller.
// http://stackoverflow.com/questions/35160483/empty-listmultipartfile-when-trying-to-upload-many-files-in-spring-with-ng-fil
arrayKey: ''
}).then(function (response) {
// log
}, function (response) {
// log
}, function (event) {
// log that file loaded
});
}
}
Java Spring Controller:
#PostMapping(value="upload-test")
public ResponseEntity<?> uploadTest(#RequestBody List<MultipartFile> file) {
try {
LOGGER.info("Received file set of size: " + file.size());
for (int i = 0; i < file.size(); i++) {
// testing, should be debug
MultipartFile singleFile = file.get(i);
String fileName =singleFile.getName();
String originalFileName = singleFile.getOriginalFilename();
LOGGER.info("Handling file: " + fileName);
LOGGER.info("Handling file (original): " + originalFileName);
LOGGER.info("File size: " + singleFile.getSize());
LOGGER.info("--");
}
return ResponseEntity.ok().body(new GeneralResponse("Handled file list of size: " + file.size()));
} catch (Exception ex) {
String msg = "Error getting files";
LOGGER.error(msg, ex);
return ResponseEntity.badRequest().body(new GeneralResponse(msg, ex));
}
}
I see that my controller is being called, but there's nothing I can see in teh MultipartFile objects that tell me the relative path of the files. When I debug in my browser, I can see that the files, prior to upload, have a field of webkitRelativePath attribute which has the relative path, but I don't see how to transfer that over to the server side in Spring.
Do I need to upload one file at a time and provide the relative path for each file as an optional argument to the call?
my file system
I tried to show these csv file as url but I failed
how I can get url for file in my file system?
public DownloadFileResponse downloadFile(DownloadFileRequest req) {
//TODO: create and set ImportMarketResponse object and return the following as response data
// "EventSet Id: " + req.eventSetId;
String txt ="EventSet Id: " + req.eventSetId;
DownloadFileResponse res = new DownloadFileResponse();
res.setReturnDate(txt);
return res;
}
Get url for file:
Java 7+
Paths.get("path","to","file").toUri().toURL()
Older Versions
new File(path).toURI().toURL();