AngularJS sending file to Google Blobstore - Blob Key retrieved as 'null' - angularjs

I want to send a video file to GAE Blobstore using AngularJS, following are the code snippet.
I am getting the upload url through endpoint API call and using it in Form action field and http POST call.
When the BlobKey was retrieved it was always returned as null. The admin console has entry for the item in 'BlobUploadSession', but I could not verify whether the video file was uploaded.
How to identify whats going wrong when the BlobKey was retrieved?
HTML:
<form name="videoForm" action="{{uploadUrl}}" ng-init="init()" novalidate role="form">
<div class="form-group">
<label for="title">Video Title</label>
<input id="title" type="text" name="title" ng-model="video.title"
class="form-control"/>
</div>
<div class="form-group">
<label for="videoFile">File Path</label>
<input id="videoFile" type="file" name="videoFile" class="form-control"
onchange="angular.element(this).scope().setFile(this)"/>
</div>
<button ng-click="addVideo(videoForm)" class="btn btn-primary">Video Add
</button>
</form>
JS:
videoApp.controllers.controller('videoAddCtrl',
function ($scope, $log, $http, oauth2Provider, HTTP_ERRORS) {
$scope.video = $scope.video || {};
$scope.init = function () {
gapi.client.video.getUploadUrl().
execute(function (resp) {
$scope.$apply(function () {
if (resp.error) {
if (resp.code && resp.code == HTTP_ERRORS.UNAUTHORIZED) {
oauth2Provider.showLoginModal();
return;
}
} else {
console.log(resp.result.uploadUrl);
$scope.uploadUrl = resp.result.uploadUrl;
}
});
});
};
$scope.submit = function () {
console.log($scope.files);
console.log($scope.uploadUrl);
return $http({
method: 'POST',
url: $scope.uploadUrl,
headers: { 'Content-Type': undefined },
data: {
file: $scope.files,
},
transformRequest: function(data) {
var formData = new FormData();
angular.forEach(data, function(value, key) {
formData.append(key, value);
});
return formData;
}
}).success(function(data) {
console.log("video " + $scope.video.title + " Successfully Uploaded");
}).error(function(data){
console.log(data);
});
};
$scope.addVideo = function (videoForm) {
console.log($scope.video.title);
$scope.submit(videoForm);
};
$scope.setFile = function(element) {
$scope.$apply(function($scope) {
$scope.files = element.files;
console.log($scope.files);
});
}
});
Java Servlet:
public class UploadVideo extends HttpServlet {
private static final Logger Log = Logger.getLogger(UploadVideo.class.getName());
private BlobstoreService blobstoreService =
BlobstoreServiceFactory.getBlobstoreService();
#Override
public void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
Log.info("+Enter");
Map<String, List<BlobKey>> blobs = blobstoreService.getUploads(req);
List<BlobKey> blobKeys = blobs.get("videoFile");
Log.info("Blob Key: " + blobKeys);
if (blobKeys == null || blobKeys.isEmpty()) {
Log.info("Blob is null or empty");
res.sendRedirect("/");
} else {
Log.info("Serve blob");
res.sendRedirect("/serve?blob-key=" + blobKeys.get(0).getKeyString());
}
Log.info("-Exit");
}
}

Related

Upload Image from angularjs using Springboot to FTP

I am trying to pick a file and upload it to FTP.
For now I get the a 415 (media type unsupported) error when consuming springboot service in angularjs when sending the image.
This is my angular controller:
Controllers.controller('UploadCtrl', [ '$scope', '$http',
function($scope, $http) {
$scope.doUploadFile = function() {
var file = $scope.uploadedFile;
var url = "/ui/upload";
var data = new FormData();
data.append('uploadfile', file);
var config = {
transformRequest : angular.identity,
transformResponse : angular.identity,
headers : {
'Content-Type' : undefined
}
}
$http.post(url, data, config).then(function(response) {
$scope.uploadResult = response.data;
}, function(response) {
$scope.uploadResult = response.data;
});
};
} ]);
My Service Controller JAVA:
#POST
#Path("/upload")
#Consumes("multipart/form-data")
public String upload(#RequestParam("uploadfile") MultipartFile file) throws Exception {
try {
return "You successfully uploaded - " + file.getOriginalFilename();
} catch (Exception e) {
throw new Exception("FAIL! Maybe You had uploaded the file before or the file's size > 500KB");
}
}
For now just getting the file name. What am 'I doing wrong when consuming the POST ?
Thank you in advance
try this:-
HTML
<img ng-src="{{profilePicturePath}}" class="img-responsive"
alt="Image Not found" style="height:150px; width: 150px;">
<input type="file" class="form-control" style="display: none;"
file-model="profileFile" multiple name="profileFile"
id="profileFile" accept="image/*"/>
JS
$scope.profileFile = null;
$scope.$watch('profileFile', function (profileFile) {
if (profileFile && profileFile.name) {
if (profileFile.size / 1012 < 512) {
if (profileFile.type.startsWith("image/")) {
uploadProfilePicture(profileFile);
}
}
}
});
function uploadProfilePicture(profileFile) {
aspirantService.uploadProfilePicture(profileFile).then(function (response) {
getProfilePicturePath();
});
}
this.uploadProfilePicture = function (file) {
var fd = new FormData();
fd.append("doc", file);
return $http.post(Server.url + 'aspirant/pic/', fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
});
};
and JAVA
#Path("pic")
#POST
#Consumes(MediaType.WILDCARD)
public Response uploadProfilePicture(MultipartFormDataInput input, #Context UserSession session) {
for (Map.Entry<String, List<InputPart>> entry : input.getFormDataMap().entrySet()) {
List<InputPart> list = entry.getValue();
for (Iterator<InputPart> it = list.iterator(); it.hasNext();) {
InputPart inputPart = it.next();
try {
MultivaluedMap<String, String> header = inputPart.getHeaders();
String fileName = RequestHeaderInfo.getFileName(header);
String contentType = RequestHeaderInfo.getContentType(header);
InputStream inputStream = inputPart.getBody(InputStream.class, null);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
//here code for write file
return Response.ok(proxy).build();
} catch (Exception ex) {
logger.log(Level.SEVERE, "Error while getting document!", ex);
}
}
}
return Response.ok().build();
}

Uploading Excel File in MVC using angularjs. HttpPostedFileBase is empty

I am trying to upload an excel file in mvc using angular js. Following is my view code:
<div class="browsebtn" ng-controller = "serviceablectrlr"><input type="file" id="dataFile" name="uploadFile" data-max-size="2097152" accept=".xls, .xlsx" onclick="$('#fileError').hide();" />
</div>
<input id="btnUploadExcel" type="button" value="Upload" ng-click="UploadConfirmation()" class="btn btn-yellow" />
Following is my controller Code :
var app = angular.module('ProductCatalog');
app.controller('serviceablectrlr', function ($scope, $http) {
var apiURL = $("#ProductCatalogApiUrl").val();
var ClearFile = function () {
$("#dataFile").val('');
}
// pass file object and url to this method
$scope.UploadConfirmation = function () {
alert("sana");
var formData = new FormData();
var totalFiles = document.getElementById("dataFile").files.length;
for (var i = 0; i < totalFiles; i++) {
var file = document.getElementById("dataFile").files[i];
var ext = file.name.split(".")[1];
if ((ext == "xls" || ext == "xlsx") && file.size < (Math.pow(1024, 3) * 2)) {
formData.append("dataFile", file);
$http({
method: 'POST',
url: apiURL + "/BulkInsertion",
data: formData,
dataType: 'json',
headers: { 'Content-Type': undefined},
transformRequest: angular.identity
}).then(function successCallback(response) {
if (response.data.ResponseData == 'Success') {
showToastrMessage('success', 'Offer saved successfully!');
$scope.data = {};
}
else {
alert('In error');
showToastrMessage('error', response.data.ResponseData);
}
},
function errorCallback(response) {
});
}
else {
}
}
}
});
And following is my MVC Controller code:
public ResponseModel Post(
HttpPostedFileBase dataFile
)
{ }
The problem i am facing is that the HttpPostedFileBase is null even though i am sending the correct parameters.
I have referred to the following question which is exactly my problem other than I am working on excel file uploading.
HttpPostedFileBase is null when uploading files with Angular
Any help would be appreciated.
You need to write following code in your cshtml view
#using (Html.BeginForm("ActioName", "ControllerName", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div>
<input type="file" name="file" />
<input type="submit" value="OK" class="button" />
</div>
}
In MVC controller
[HttpPost]
public ActionResult UploadFile(HttpPostedFileBase myFile)
{
//Validate the fileType
// Verify that the user selected a file
if (file != null && file.ContentLength > 0)
{
//do something here...
}
}
In cae you want to do with angular js then use following code to post file
// pass file object and url to this method
this.uploadFileToUrl = function (file, uploadUrl) {
return $http({
method: 'POST',
url: uploadUrl,
headers: { 'Content-Type': undefined },
transformRequest: function() {
var formData = new FormData();
if(file){
formData.append("myFile", file);
}
return formData;
}
})
}
Add this in WebApiConfig.Register():
this.SupportedMediaTypes.Add(new MediaTypeHeaderValue("multipart/form-data"));

Adding model with image AngularJS and ASP.NET MVC

I need some help to solve this problem. To add new record to my database I'm using AngularJS and ASP.NET MVC (without reloading the page). All is working fine, but the problem appears when I'm trying to upload also image with HTML input type="file". I'm using FormData (I think it is the best way to do this?) to upload image and for the rest model properties I'm using ng-model and so on. The funny thing is that when I'm trying to save just image, without any other data then my controller gets the file but when I will add also some properties for my record like Name, Year, Author + image then the controller with only get the model properties or just single image, never both.
Here is my angulajs code:
angular.module('MovieController', [])
.controller('MovieCtrl', ['$scope', '$http', function ($scope, $http) {
$scope.model = {};
$http.get('/Manage/AddMovieVM').success(function (data) {
$scope.model = data;
});
$scope.addMovie = function () {
$http.post('/Manage/Add', $scope.new.Movie).success(function (data) {
$scope.model.Movies.push(data);
$scope.showAddForm(false);
});
};
//upload files
var formData = new FormData();
$scope.LoadFileData = function (files) {
for (var file in files) {
formData.append("file", files[file]);
}
};
$scope.submit = function () {
$http.post("/Manage/Edit", formData, {
withCredentials: true,
headers: { 'Content-Type': undefined },
transformRequest: angular.identity
}).success(function (response) {
console.log('succes');
});
};
}]);
Here is my back-end code, ASP.NET MVC:
[HttpPost]
public ActionResult Add(Movie model, HttpPostedFileBase file)
{
var files = Request.Files;
var fileName = Path.GetFileName(file.FileName);
if (ModelState.IsValid)
{
using (var db = new MovieSubtitlesContext())
{
var movie = new Movie()
{
MovieTitle = model.MovieTitle,
MovieDescription = model.MovieDescription,
MovieDirector = model.MovieDirector,
MovieRating = model.MovieRating,
MovieImage = fileName
};
db.Movies.Add(movie);
db.SaveChanges();
return Json(movie, JsonRequestBehavior.AllowGet);
}
}
return View();
}
Here is my view:
<input type="text" class="form-control" placeholder="Title" ng-model="new.Movie.MovieTitle" />
<textarea rows="15" cols="50" class="form-control" ng-model="new.Movie.MovieDescription" placeholder="Description"></textarea>
//director and rating similar to first input
<input id="imgInp" type="file" aria-label="Add photos to your post" class="upload" name="file" onchange="angular.element(this).scope().LoadFileData(this.files)" multiple="" accept="image/*">
I tried a lot. For example to save all in one function like this:
$scope.addMovie = function () {
$http.post('/Manage/Edit', $scope.new.Movie, formData, {
withCredentials: true,
headers: { 'Content-Type': undefined },
transformRequest: angular.identity
}).success(function (data) {
$scope.model.Movies.push(data);
$scope.showAddForm(false);
});
};
I think it is a good idea because there are two post requests but it doesn't work anyway. To my button I tried to call two functions like this but still nothing.
<button type="button" class="btn btn-success" ng-click="addMovie(); submit()">Save</button>
I really don't know what I'm doing wrong and how I can save image with other model properties. (When I'm passing the image name in my textbox it is working fine, but that's not the point, (for example I already have in my folder "batman.jpg" then I just need to pass "batman.jpg" in my:
<input type="text" class="form-control" placeholder="Img" ng-model="new.Movie.MovieImage" required />
//Update for Nadeem
MVC Controller:
[HttpPost]
public ActionResult AddMovie(Movie model, HttpPostedFileBase file)
{
if (ModelState.IsValid)
{
if (file != null && file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/Content/ImagesC"), fileName);
file.SaveAs(path);
model.MovieImage = fileName;
}
using (var db = new MovieSubtitlesContext())
{
var movie = new Movie()
{
MovieTitle = model.MovieTitle,
MovieDescription = model.MovieDescription,
MovieDirector = model.MovieDirector,
MovieGenre = model.MovieGenre,
MovieDuration = model.MovieDuration,
MovieTrailer = model.MovieTrailer,
ImdbLink = model.ImdbLink,
MovieRating = model.MovieRating,
MovieImage = model.MovieImage,
ReleaseDate = model.ReleaseDate
};
db.Movies.Add(movie);
db.SaveChanges();
return Json(movie, JsonRequestBehavior.AllowGet);
}
}
return View();
}
Here is also my angularjs controller code for AddMovie
$scope.uploadPic = function (file) {
file.upload = Upload.upload({
url: '/Manage/AddMovie',
data: {
file: file,
MovieTitle: $scope.new.Movie.MovieTitle,
MovieDescription: $scope.new.Movie.MovieDescription,
MovieDirector: $scope.new.Movie.MovieDirector,
ReleaseDate: $scope.new.Movie.ReleaseDate,
MovieGenre: $scope.new.Movie.MovieGenre,
MovieDuration: $scope.new.Movie.MovieDuration,
MovieTrailer: $scope.new.Movie.MovieTrailer,
ImdbLink: $scope.new.Movie.ImdbLink,
MovieRating: $scope.new.Movie.MovieRating
}
});
file.upload.then(function (response) {
$timeout(function () {
file.result = response.data;
});
}, function (response) {
if (response.status > 0)
$scope.errorMsg = response.status + ': ' + response.data;
}, function (evt) {
// Math.min is to fix IE which reports 200% sometimes
file.progress = Math.min(100, parseInt(100.0 * evt.loaded / evt.total));
});
};

Async file upload (using FormData) with Node.JS Express and Formidable in the server side

I want to upload files async to Node.JS Express.
I'm pretty confident with my HTML and Javascript because I've used them several times in the past with ASP.NET in the serverside.
Now I want to use the same clientside code with Node.JS with Express in the serverside.
HTML:
<form id="form">
<div class="form-group">
<label>XML files (1 or many)</label>
<input type="file" class="form-control" id="files" name="dummy" multiple ng-disabled="processing" accept=".xml" />
</div>
<div class="form-group">
<button class="btn btn-default" ng-click="process()" ng-disabled="processing">
<span ng-show="processing">Processing...</span>
<span ng-show="!processing">Convert</span>
</button>
</div>
</form>
Javascript:
$scope.process = function () {
$scope.processing = true;
var formData = new FormData();
for (var i = 0; i < document.getElementById('files').files.length; i++) {
formData.append('file' + i, document.getElementById('files').files[i]);
}
var httpRequest = $http({
method: 'post',
url: "/api/parser/parse",
data: formData,
params: {
},
transformRequest: angular.identity,
headers: { 'Content-Type': undefined }
});
httpRequest.success(function (response) {
$scope.response = response;
if (response.error) {
toaster.pop('error', response.message);
return;
}
toaster.pop('success', "", "Finished processing");
});
httpRequest['finally'](function () {
$scope.processing = false;
});
};
}]);
Serverside code (Node.JS):
var express = require('express');
var formidable = require('formidable');
var _ = require('underscore');
var router = express.Router();
router.post('/parse', function(req, res, next) {
var form = new formidable.IncomingForm();
form.parse(req, function(err, fields, files) {
if (err) {
console.error(err.message);
return;
}
console.log(files.length); // Is outputting "undefined"
});
res.json({
error: false
});
});
How can I access the files being submitted?
As you can see, console.log(files.length) is giving me undefined

Request with different files in danialfarid angular-file-upload

I used danialfarid angular-file-upload to upload files.
I want to send request with two files and one json string.
Each two files has different params in Server side.
Server side used spring rest.
How can I send?
Here is my angular service.
services.factory('USR008Service', function($resource, $http, $upload) {
return {
insertUSR008FUN01 : function(talent, talentFile, coverImg) {
return $upload.upload({
url: contextRoot + '/insertUSR008FUN01',
fields: {
'USR008REQ02': JSON.stringify(talent),
},
file: coverImg,
fileFormDataName : 'coverImg'
});
}
}
});
Here is my Server Side Controller.
#RequestMapping(value = URIConstant.insertUSR008FUN01, method = RequestMethod.POST, produces = "application/json; charset=utf-8")
public #ResponseBody USR008RES02 insertUSR008FUN01(#RequestParam(value = "talentFile", required = false) MultipartFile talentFile, #RequestParam(value = "USR008REQ02") String jsonData,
#RequestParam(value = "coverImg", required = false) MultipartFile coverImg) {
USR008RES02 result = null;
try {
Gson gson = new GsonBuilder().create();
USR008REQ02 usr008req02 = gson.fromJson(jsonData, USR008REQ02.class);
result = usr008SEV.insertUSR008RES02(usr008req02, talentFile, coverImg);
} catch (SystemException e) {
logger.error("insertUSR008FUN01 function has been failed.");
throw new SystemException("insertUSR008FUN01 function has been failed.", e);
}
return result;
}
This is how I implemented this in my app.
HTML
<label for="uploadDomainFile">Select File</label>
<input type="file" class="form-control" id="uploadDomainFile" ng-model="fileDomain" ng-file-select>
<label for="uploadLegalFile">Select File</label>
<input type="file" id="uploadLegalFile" ng-model="fileLegal" ng-file-select>
JS
//controller
$scope.createDomain = function () {
adminService.createDomain($scope.domain, $scope.fileLegal, $scope.fileDomain);
};
//service
//ommitting irrelevant code
uploadOwlFile(fileLegal, domain.id);
uploadOwlFile(fileDomain, domain.id);
var uploadOwlFile = function(file, domainId) {
if (file && !!file.value) {
$upload.upload({
url: '/api/space/' + domainId + '/owl',
data: { fileType: file.fileType },
file: file.value[0]
})
.progress(function(evt){
console.log('progress: ' + parseInt(100 * evt.loaded / evt.total))
})
.success(function(data, status, headers, config){
console.log('success', 'file: ' + config.file.name + ' successfully uploaded');
return true;
})
.error(function(err, status){
console.log('failure', err);
return false;
})
} else {
return true;
}
};
Returning true or false is based on the status of the file upload.
So, my method involves using two ng-models for the 2 inputs and uploading the file separately.

Resources