I have been struggling to upload a file using Angular JS to POST to my Java Play Framework RESTful backend as a lot of examples I have found don't apply to me.
I am confident my Angular JS code works fine but I will share it anyway:
file-upload.html
<div data-ng-controller="uploadCtrl">
<input type="file" file-model="myFile" id="theFile" name="theFile" />
<button data-ng-click="uploadFile()">Upload</button>
</div>
file-upload-ctrl.js
"use strict";
angular.module("pamm").controller("uploadCtrl", ["$scope", "fileUploadRepository",
function($scope, fileUploadRepository) {
$scope.uploadFile = function () {
var file = $scope.myFile;
console.dir("Ctrl: " + file);
fileUploadRepository.uploadFile(file);
}
}]);
file-upload-repo.js
"use strict";
angular.module("pamm").service("fileUploadRepository", ["$q", "$log", "$rootScope", "contextEvent", "fileUploadDao",
function ($q, $log, $rootScope, contextEvent, fileUploadDao) {
var fileUploadCache = [];
(function init() {
$rootScope.$on(contextEvent.CLEAR_CONTEXT, function clearContext() {
fileUploadCache = [];
$log.info("fileUploadRepository: context cleared");
})
})();
this.uploadFile = function (file) {
var waitingDialog = $$dialog.waiting("Please wait - Uploading file");
var deferred = $q.defer();
fileUploadDao.uploadFile(file).then(function (uploadedFile) {
fileUploadCache.push(uploadedFile);
$log.debug("Repo: " + uploadedFile);
waitingDialog.close();
deferred.resolve(uploadedFile);
}, function (error) {
deferred.reject(error);
waitingDialog.close();
});
return deferred.promise;
};
}]);
The layer up from Repo
"use strict";
angular.module("pamm").service("fileUploadDal", ["$http", "$q", "$log", function ($http, $q, $log) {
this.http = (function serviceCaller() {
return {
/**
* #returns {promise}
*/
POST: function (apiPath, fd) {
var deferred = $q.defer();
$http.post(apiPath, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
}).then(function (results) {
deferred.resolve(results.data);
}, function (e) {
deferred.reject(e);
});
return deferred.promise;
}
}
})();
$log.info("fileUploadDal:serviceCaller Instantiated");
}]);
Java
Http.MultipartFormData file = request().body().asMultipartFormData();
Where can I go next with this? Hence I can't access the name of the HTML input because of the way my Angular is written.
What can I do to file to save it the file to a directory I desire.
Thanks,
Have you tried this:
import java.io.File;
File fileFromRequest = request.body().asRaw().asFile();
fileFromRequest.renameTo(new File("path/to/dir","filename.png"));
public ServiceResult execute(final Http.MultipartFormData request)
{
final String DIRECTORY = "C:\\SAVE_DIRECTORY\\SUB_FOLDER\\uploads";
List<Http.MultipartFormData.FilePart> targetFiles = request.getFiles();
for (int i = 0; i < targetFiles.size(); i++)
{
File file = targetFiles.get(i).getFile();
String fileName = targetFiles.get(i).getFilename();
file.renameTo(new File(DIRECTORY, fileName));
}
return new ServiceResult(Json.toJson(targetFiles));
}
Related
I am trying to upload multiple files at a time using Spring Boot and AngularJS.
Spring Boot file
#RequestMapping(value = "/fileUpload", method = RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE )
public #ResponseBody boolean UploadFile(#RequestParam(value = "file", required = true) MultipartFile[] files){
Here I am getting the value of MultipartFile[] files as MultipartFile[0]#17615 instead of an array of MultipartFiles. The length of the array is 0.
HTML File
<input type="file" file-model="myFile" name="filePath" ng-model="filePath" on-click="false" multiple required>
AngularJS file
app.directive('fileModel', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var model = $parse(attrs.fileModel);
var modelSetter = model.assign;
element.bind('change', function(){
scope.$apply(function(){
modelSetter(scope, element[0].files);
});
});
}
};
}]);
app.service('fileUpload', ['$http', 'growl', '$state', function ($http, growl, $state) {
this.uploadFileToUrl = function(file, uploadUrl){
var fd = new FormData();
for(let i=0;i<file.length;i++){
fd.append('file', file[i]);
}
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.success(function(data, status, headers) {
.....
})
.error(function(error){
.....
});
}
}]);
app.controller('uploadauditfilectrl', ['$scope', 'fileUpload', '$cookieStore', function($scope, fileUpload, $cookieStore){
$scope.uploadFile = function(){
var file = this.myFile;
var uploadUrl = "/fileUpload/";
fileUpload.uploadFileToUrl(file, uploadUrl);
};
}]);
Can anyone please tell me the mistake I am doing.
I can't download file from my friend service java code from angular that i implement and i don't know how to implement download file from angular please help me
My Code Angular
private _download$ = new Subject<void>();
**this._download$.pipe(switchMap(()=>this._downloadFile())).subscribe(resultBlob =>{
console.log("Success to Next ")
this.loadFile(resultBlob)
},(exception:any)=>{
console.log("exception: ",exception)
},()=>{
console.log("Complete: ")
})
}**
**private _downloadFile(){
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/octet-stream',
responseType : 'blob',
Accept : 'application/octet-stream',
observe : 'response'
})
};**
return this.http.get<Blob>('/col-corecollection-service/exclusion/download-file/'+this.exclusionCode,httpOptions)
}
private download(){
this._download$.next();
}
loadFile(data: any) {
var blob = new Blob([data], {type: 'application/octet-stream'});
var downloadURL = window.URL.createObjectURL(data);
window.open(downloadURL);
}**
And I have code service that my friend implement like this
#GetMapping("/exclusion/download-file/{exclCode}")
#ResponseStatus(HttpStatus.OK)
public ResponseEntity<Resource> exclusionDownloadFile(
#Size(min = 1, max = 50)
#PathVariable String exclCode
) {
if (!this.exclusionService.existsExclusionById(exclCode)) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Exclusion code " + exclCode + " not found.", null);
}
SearchExclFilenameExclBlobByIdResponse downloadFile = this.exclusionService.searchExclFilenameExclBlob(exclCode);
byte[] fileData = downloadFile.getExclBlob();
Resource resource = new InputStreamResource(new ByteArrayInputStream(fileData));
return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + downloadFile.getExclFilename() + "\"")
.body(resource);
}
when i click my download button and then it can't downloadFile to me please help
Try passing responseType outside headers
Remove responseType from header:
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/octet-stream',
Accept : 'application/octet-stream',
observe : 'response'
})
};
Here is updated code for passing responseType outside headers:
return this.http.get<Blob>('/col-corecollection-service/exclusion/download-file/'+this.exclusionCode,{headers: httpOptions.headers, responseType: 'blob'})
Then if you want download use fileSaver:
var file = new Blob([data], { type: "application/octet-stream" });
this.fileSaverService.save(file);
I use ngx-filesaver which provides the fileSaver directive.
<button class="mdi mdi-download btn btn-primary"
fileSaver
[fileName]="'yourfile.xxx'"
[url]="'/col-corecollection-service/exclusion/download-file/' + this.exclusionCode"
(change)="upload($event)">
Download
</button>
I am trying to post a file (single file or multiple files) along with some JSON data using AngularJS and Spring MVC.
I tried as shown below:
JS:
(function () {
'use strict';
var myApp = angular.module('app');
myApp.controller('filesWithJSONController', function ($scope, fileUploadService) {
$scope.uploadFile = function () {
var file = $scope.myFile;
var uploadUrl = myApplnURL + '/showInfo/getInformationTest';", //Url of web service
var fd=new FormData();
angular.forEach($scope.files,function(file){
fd.append('file',file);
});
fd.append('properties', new Blob([JSON.stringify({
"name": "root",
"password": "root"
})], {
type: "application/json"
}));
promise = fileWithJSONService.sendInformation(fd,uploadUrl);
promise.then(function (response) {
$scope.serverResponse = response;
}, function () {
$scope.serverResponse = 'An error has occurred';
})
};
});
})();
(function () {
'use strict';
var myApp = angular.module('app');
myApp.service('fileWithJSONService', function ($http, $q) {
this.sendInformation = function (fd, uploadUrl) {
var deffered = $q.defer();
var config = {
headers : {
'Content-Type': undefined
}
}
$http.post(uploadUrl, fd, config).then(function (response) {
console.log("response " + response);
}, function (errResponse) {
console.error('Error in request' + errResponse);
deferred.reject(errResponse);
});
...
Spring Controller:
#Controller
#RequestMapping("/showInfo")
public class InfoController{
#RequestMapping(value = "/getInformationTest", method = RequestMethod.POST, consumes = {"multipart/form-data"})
#ResponseBody
public String sendInformationTest(#RequestPart("properties") ConnectionProperties properties, #RequestPart("file") List<MultipartFile> multiPartFileList){
System.out.println("In spring controller");
//business logic
}
With the above code, it is showing the multiPartFileList size as zero in Spring Controller.
But if I change the code to take only one file instead of multiple files, it is showing the file information successfully. Any input?
try with:
var fd = new FormData();
fd.append('file', file);//replace with forEach
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,//overrides Angular's default serialization, leaving our data intact.
headers: {'Content-Type': undefined}//lets the browser detect the correct Content-Type as multipart/form-data, and fill in the correct boundary.
})
.success(function(){})
.error(function(){});
Backend - Spring:
#RequestMapping(value ="/upload", method = RequestMethod.POST)
public ResponseEntity handleFileUpload(#RequestParam("file") MultipartFile[] files){
//add the others params & logic
}
I want to upload to server multiple files. Here is my Angular code:
app.directive('fileModel', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
var model = $parse(attrs.fileModel);
var modelSetter = model.assign;
element.bind('change', function () {
scope.$apply(function () {
modelSetter(scope, element[0].files);
});
});
}
};
}]);
And part of the controller:
var fd = new FormData();
fd.append('files', $scope.file);
fd.append('ticketDto', JSON.stringify(data));
$http({
method: 'POST',
url: url,
headers: {
'Content-Type': undefined
},
data: fd,
arrayKey: '',
transformRequest: function (data, headersGetterFunction) {
return data;
}
})
The problem is that in controller:
public void createTicket(#RequestParam(value = "files", required = false) List<MultipartFile> files,
Authentication authentication,
#RequestParam(value = "ticketDto", required = false) String name)
'files' list is always empty (I also tried MultipartFile[] instead of list). It works only if in directive return not all files, but one, for example:
scope.$apply(function () {
modelSetter(scope, element[0].files[0]);
});
instead of
scope.$apply(function () {
modelSetter(scope, element[0].files);
});
Finally I got it. The solution is to add all files to the FormData apart, not as list or array:
angular.forEach($scope.file, function (value, key) {
fd.append('files', value);
})
And then in Spring controller:
public void createTicket(#RequestParam(required = false) MultipartFile[] files)
The array contains all appended files.
I have angularjs And spring rest file upload it work well but i need to change file upload in html file to dropzone.js or any drag drop file upload,I tried dropzone.js library but I couldn't integrate it with angular ,Can any one help me how can i do that?
Angularjs controller
$scope.document = {};
$scope.setTitle = function(fileInput) {
var file=fileInput.value;
var filename = file.replace(/^.*[\\\/]/, '');
var title = filename.substr(0, filename.lastIndexOf('.'));
$("#title").val(title);
$("#title").focus();
$scope.document.title=title;
};
$scope.uploadFile=function(){
var formData=new FormData();
formData.append("file",file.files[0]);
$http.post('/app/newDocument', formData, {
transformRequest: function(data, headersGetterFunction) {
return data;
},
headers: { 'Content-Type': undefined }
}).success(function(data, status) {
console.log("Success ... " + status);
}).error(function(data, status) {
console.log("Error ... " + status);
});
};
});
html form
<form ng-submit="uploadFile()" class="form-horizontal"
enctype="multipart/form-data">
<input type="file" name="file" ng-model="document.fileInput" id="file" />
<input type="text" class="col-sm-4" ng-model="document.title" id="title" />
</form>
Rest Controller
#RequestMapping(value="/newDocument", method = RequestMethod.POST)
public void UploadFile(MultipartHttpServletRequest request,
HttpServletResponse response) throws IOException {
Attachment attachment=new Attachment();
Iterator<String> itr=request.getFileNames();
MultipartFile file=request.getFile(itr.next());
String fileName=file.getOriginalFilename();
attachment.setName(fileName);
File dir = new File("D:\\file");
if (dir.isDirectory())
{
File serverFile = new File(dir,fileName);
BufferedOutputStream stream = new BufferedOutputStream(
new FileOutputStream(serverFile));
stream.write(file.getBytes());
stream.close();
}else {
System.out.println("not");
}
}
I would personally use a dedicated directive such as the excellent:
https://github.com/danialfarid/angular-file-upload
https://github.com/flowjs/ng-flow
These take care of the boilerplate code and let you focus on styling and creating an upload service that works in sync with your API.