Ng-File-Upload to Save PDF Blob to Database - angularjs

I'm editing this post to show my latest attempt per suggestions below.
I have been searching the forums trying to find a solution. I have an ASP.NET MVC Application in which I use Angular. I am trying to use danialfarid/ng-file-upload to allow users to upload PDFs which then get saved to the database as binary data (not my idea, but I have to do it that way).
I have the following (taken from the examples) in my HTML:
File:<input type="file" ngf-select ng-model="picFile" name="file" accept="image/*" ngf-max-size="2MB" required ngf-model-invalid="errorFile"><br />
<img ngf-thumbnail="picFile" class="thumb"> <button ng-click="picFile = null" ng-show="picFile">Remove</button><br />
<button type="button" class="btn btn-primary" ng-click="uploadPic(picFile)">Upload</button>
And this in my Angular controller:
$scope.uploadPic = function (files) {
file.upload = Upload.upload({
url: '/SSQV4/SSQV5/Document/UploadEMRDocument',
data: {file: files}
})
}
My MVC Controller:
namespace SSQV5.Controllers
{
public class DocumentController : ApiController
{
public async Task<IHttpActionResult> UploadEMRDocument()
{
try
{
var provider = new MultipartMemoryStreamProvider();
await Request.Content.ReadAsMultipartAsync(provider);
var f = provider.Contents.First(); // assumes that the file is the only data
if (f != null)
{
var filename = f.Headers.ContentDisposition.FileName.Trim('\"');
filename = Path.GetFileName(filename);
var buffer = await f.ReadAsByteArrayAsync();
//buffer now contains the file content,
//and filename has the original filename that was uploaded
//do some processing with it (e.g. save to database)
}
else
{
return BadRequest("Attachment failed to upload");
}
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
return Ok();
}
}
}
This code never hits the MVC Controller at all. I'm obviously missing something, but I haven't the slightest clue as to what it could be. Any assistance is greatly appreciated!

You need to extract the file content out of the form data.
Below is how I do this (using ng-file-upload in the same manner as you from the front end) to upload attachments in my application.
public async Task<IHttpActionResult> UploadAttachment()
{
// Check if the request contains multipart/form-data.
try
{
var provider = new MultipartMemoryStreamProvider();
await Request.Content.ReadAsMultipartAsync(provider);
var f = provider.Contents.First(); // assumes that the file is the only data
if (f != null)
{
var filename = f.Headers.ContentDisposition.FileName.Trim('\"');
filename = Path.GetFileName(filename);
var buffer = await f.ReadAsByteArrayAsync();
//buffer now contains the file content,
//and filename has the original filename that was uploaded
//do some processing with it (e.g. save to database)
}
else
{
return BadRequest("Attachment failed to upload");
}
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
return Ok();
}

When you configure the upload, you specify the URL where the file will be posted to:
file.upload = Upload.upload({
url: 'myMVC/MyMethod',
data: {file: file}
})

Related

How can i generate a blob url?

I have a function that will determine if the gif is animated or non-animated. Everything is working fine, until i upload those gif to the server, and load it, the blob url is a empty string. How can i generate a blob url for this?
Due to the blob url being empty string, i get parameter 1 is not of type 'blob'
The function below determines if the gif is animated or not.
$scope.isNotAnimatedGIF = function(file) {
var reader = new FileReader();
return new Promise(function(resolve, reject) {
reader.onload = function (e) {
var gifInfo = gify.getInfo(reader.result);
if (gifInfo.images.length <= 1) {
file.animatedGIF = false;
resolve(true);
} else {
file.animatedGIF = true;
resolve(false);
}
}
reader.readAsArrayBuffer(file);
});
}
I am using Angular 1.4.10
Thank you !
You can use URL.createObjectURL() to create Blob url.
The URL.createObjectURL() static method creates a DOMString containing a URL representing the object given in the parameter. The URL lifetime is tied to the document in the window on which it was created. The new object URL represents the specified File object or Blob object.
DEMO
function createbloburl(file, type) {
var blob = new Blob([file], {
type: type || 'application/*'
});
file = window.URL.createObjectURL(blob);
return file;
}
document.querySelector('#file').addEventListener('change', function(e) {
var file = e.currentTarget.files[0];
if (file) {
file = createbloburl(file, file.type);
document.querySelector('iframe').src = file;
//console.log(file)
}
})
<input id="file" type="file">
<iframe src=""></iframe>
try this reader.readAsDataURL(Blob|File).
you can find more from here

Create file on client side and send to server

i want to create a file in client side using Angular or Javascript and send it to server.
Using MVC controller my server function is
public void SavePivotFile(HttpPostedFileBase file)
{
try
{
if (file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~"), System.Configuration.ConfigurationManager.AppSettings["reportsFolder"].ToString(), fileName);
file.SaveAs(path);
}
}
catch(Exception e)
{
throw;
}
}
Now, in my client side, i have a object that i want to send in SavePivotFile like a file. I tried this but doesnt work. The object 'options' is JSON.
$http({
method: 'GET',
url: '/FileManager/SavePivotFile',
params: {
file: options,
}
}).then(function successCallback(response) {
showNotification('The changes have been saved.', 'info');
}, function errorCallback(response) {
showNotification('Failed to save the file.', 'error');
});
Also i tried to create new FormData() before send but also doesn't work. How cat take options JSON object and pass it to server like file?
//C# Code
[HttpPost]
[Route('FileManager/SavePivotFile')]
// you can use [Allow(Role)] to allow particular role. Google it!
public void SavePivotFile(HttpPostedFileBase file)
{
try
{
if (file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~"), System.Configuration.ConfigurationManager.AppSettings["reportsFolder"].ToString(), fileName);
file.SaveAs(path);
}
}
catch(Exception e)
{
throw;
}
}
//Angular Code
$http.post('FileManager/SavePivotFile',options)//Optionsistheobjectuwanttosend
.success(function(res){
//your code. since the c# method isvoid you will not get any response
})
.error(function(e){
//your error handling
})
The HttpPostedFileBase model should be similar to options. That way you can access the JSON in c#.
Let me know if this works.

File upload won't work with angular-file-upload and Spring

I am trying to make a simple file upload possible but Spring does not want to play with me.
This is the endpoint for file uploads - currently not doing a lot:
#PostMapping(WordEmbeddingApiPaths.UPLOAD_MODEL)
#RequestMapping(method=RequestMethod.POST, consumes = {"multipart/form-data"})
public ResponseEntity<WordVectorListDto> uploadModel(
#ModelAttribute("file") MultipartFile file,
// #RequestBody Object obj,
RedirectAttributes redirectAttributes) {
LOGGER.debug("POST uploadModel");
return new ResponseEntity<WordVectorListDto>((WordVectorListDto)null, HttpStatus.OK);
}
I've tried several things but it all ends up in different errors. I've just tried to use #RequestBody because I thought maybe that's the trick but then I get an exception saying:
Content type 'multipart/form-data;boundary=----WebKitFormBoundarycV8dFSvDV6U9OwJq' not supported
or
Content type 'multipart/form-data' not supported
depending on what I just tried.
If I go with #RequestPart("file") MultipartFile file I see
Required request part 'file' is not present
which is similar for #RequestParam("file").
I have no idea what's so hard on this but I hope somebody can tell me how I can get that file from the client.
Below you can see the request I've sent to the endpoint:
Is this request okay?
Web Client:
var uploader = $scope.uploader = new FileUploader({
url: 'http://localhost:8080/rest-api/dl4j/we/uploadModel'
});
uploader.onAfterAddingFile = function($modelFile) {
console.info('onAfterAddingFile', $modelFile);
var fd = new FormData();
fd.append('file', $modelFile.file);
$http.post($modelFile.url, fd, {
headers: {
'Content-Type': undefined
},
transformRequest: angular.identity
})
.then(
function (data) {
alert("upload success");
},
function (data, status) {
alert("upload error");
}
);
};
index.html
<label class="btn btn-default btn-file" style="float:right;">
Upload
<input
type="file"
style="display: none;"
name="file"
multiple
nv-file-select
uploader="uploader">
</label>
Here is how i didi it:
#RequestMapping(value="/uploadFile", method=RequestMethod.POST)
public #ResponseBody String handleFileUpload(
#RequestParam("file") MultipartFile file){
String name = "test11";
if (!file.isEmpty()) {
try {
byte[] bytes = file.getBytes();
BufferedOutputStream stream =
new BufferedOutputStream(new FileOutputStream(new File(name + "-uploaded")));
stream.write(bytes);
stream.close();
return "You successfully uploaded " + name + " into " + name + "-uploaded !";
} catch (Exception e) {
return "You failed to upload " + name + " => " + e.getMessage();
}
} else {
return "You failed to upload " + name + " because the file was empty.";
}
}
and dont forget to register the multipart resolver:
#Bean
public MultipartResolver multipartResolver() {
org.springframework.web.multipart.commons.CommonsMultipartResolver multipartResolver = new org.springframework.web.multipart.commons.CommonsMultipartResolver();
multipartResolver.setMaxUploadSize(10000000);
return multipartResolver;
}
here is the html code ... take a look at the name/id of the input fields ..
File1 to upload:
Name1: <input type="text" name="name">
File2 to upload: <input type="file" name="file">
Name2: <input type="text" name="name">
<input type="submit" value="Upload"> Press here to upload the file!
</form>

Get an image of a vbhtml view as a byte array and save it to an oracle database

I need help on an mvc application in vb.net. In general terms I need to receive an image through the view and get it to work on the controller. I need to do this to convert the image to a byte array and save it to an oracle database. So my idea is to get the image and in the controller to convert it to a byte array or maybe there is some way to get the image already as a byte array and pass that array to the controller to save it to the database.
something like this its my View :
<div class="span11">
<div class="span4" id="depnac">
#Html.LabelFor(Function(m) m.DepNacPER)
#Html.DropDownListFor(Function(m) m.DepNacPER, Model.DepNacPER, New With {.class = "form-control"})
</div>
and this is my Model :
<Display(Name:="Region of birth")>
<Required(ErrorMessage:="you must select a option")>
Property DepNacPER As SelectList
I'm working on an ASP.NET Core app right now that uploads images. The image comes through to the controller via the request as a Stream. I'm then creating an Image object from that Stream but you could just read the data from it directly. That said, you might want to try to create an Image object to confirm that the data does represent a valid image.
Here's some relevant code from the view's script:
function uploadImage()
{
// This is a file upload control in a hidden div.
var image = $("#imageFile");
if (image[0].files.length > 0)
{
var formData = new FormData();
formData.append(image[0].files[0].name, image[0].files[0]);
var xhr = new XMLHttpRequest();
xhr.open("POST", "#Url.Content("~/events/uploadimage")");
xhr.send(formData);
xhr.onreadystatechange = function ()
{
if (xhr.readyState === 4 && xhr.status === 200)
{
var response = JSON.parse(xhr.responseText);
if (response.saveSuccessful)
{
// ...
} else
{
window.location.replace("#Url.Content("~/error")");
}
}
}
xhr.onerror = function(err, result)
{
alert("Error: " + err.responseText);
}
}
}
I'm in the process of replacing that code with some jQuery that does the heavy lifting but haven't got that far yet.
Here's some relevant code from the action:
[HttpPost]
public IActionResult UploadImage()
{
var requestForm = Request.Form;
StringValues tempImageFileNames;
string tempImageFileName = null;
string imageUrl = null;
var saveSuccessful = true;
var requestFiles = requestForm.Files;
if (requestFiles.Count > 0)
{
// A file has been uploaded.
var file = requestFiles[0];
using (var stream = file.OpenReadStream())
{
try
{
using (var originalImage = System.Drawing.Image.FromStream(stream))
{
// Do whatever you like with the Image here.
}
}
catch (Exception)
{
saveSuccessful = false;
}
}
}
if (saveSuccessful)
{
return Json(new {saveSuccessful, tempImageFileName, imageUrl});
}
else
{
return Json(new {saveSuccessful});
}
}
Sorry, it didn't occur to me at first that you're after VB code and this is C#. Hopefully you can still get the idea and I'll take the hit if someone dislikes the answer.

why cant i write a second file to gridfs without refreshing template view in a MEAN app?

I am having a problem writing a second audio file to gridfs. I am using ng-file-upload to pick a file, pass the file/binary data to gridfs, and write it to the database. The first file works fine, however unless i load a different view first, then go back to my audio view/template page i get this error everytime:
TypeError: path must be a string
at TypeError (native)
at Object.fs.open (fs.js:540:11)
at ReadStream.open (fs.js:1673:6)
at new ReadStream (fs.js:1660:10)
at Object.fs.createReadStream (fs.js:1608:10)
at NativeConnection.<anonymous> (Z:\techFilez\webApp\MyPiCloud\routes\IO\writeFile.js:42:29)
at NativeConnection.g (events.js:260:16)
at emitNone (events.js:67:13)
at NativeConnection.emit (events.js:166:7)
at open (Z:\techFilez\webApp\MyPiCloud\node_modules\mongoose\lib\connection.js:518:11)
at NativeConnection.Connection.onOpen (Z:\techFilez\webApp\MyPiCloud\node_modules\mongoose\lib\connection.js:527:5)
at Z:\techFilez\webApp\MyPiCloud\node_modules\mongoose\lib\connection.js:487:11
at Z:\techFilez\webApp\MyPiCloud\node_modules\mongoose\lib\drivers\node-mongodb-native\connection.js:71:5
at Z:\techFilez\webApp\MyPiCloud\node_modules\mongoose\node_modules\mongodb\lib\db.js:232:5
at connectHandler (Z:\techFilez\webApp\MyPiCloud\node_modules\mongoose\node_modules\mongodb\lib\server.js:333:7)
at g (events.js:260:16)
Z:\techFilez\webApp\MyPiCloud\node_modules\mongoose\node_modules\mongodb\lib\server.js:336
process.nextTick(function() { throw err; })
^
TypeError: path must be a string
at TypeError (native)
at Object.fs.open (fs.js:540:11)
at ReadStream.open (fs.js:1673:6)
at new ReadStream (fs.js:1660:10)
at Object.fs.createReadStream (fs.js:1608:10)
at NativeConnection.<anonymous> (Z:\techFilez\webApp\MyPiCloud\routes\IO\writeFile.js:42:29)
at NativeConnection.g (events.js:260:16)
at emitNone (events.js:67:13)
at NativeConnection.emit (events.js:166:7)
at open (Z:\techFilez\webApp\MyPiCloud\node_modules\mongoose\lib\connection.js:518:11)
at NativeConnection.Connection.onOpen (Z:\techFilez\webApp\MyPiCloud\node_modules\mongoose\lib\connection.js:527:5)
at Z:\techFilez\webApp\MyPiCloud\node_modules\mongoose\lib\connection.js:487:11
at Z:\techFilez\webApp\MyPiCloud\node_modules\mongoose\lib\drivers\node-mongodb-native\connection.js:71:5
at Z:\techFilez\webApp\MyPiCloud\node_modules\mongoose\node_modules\mongodb\lib\db.js:232:5
at connectHandler (Z:\techFilez\webApp\MyPiCloud\node_modules\mongoose\node_modules\mongodb\lib\server.js:333:7)
at g (events.js:260:16)
[nodemon] app crashed - waiting for file changes before starting...
I have done several things:
i am making sure to use fs.unlink(myFile) delete from filesystem, as well as close the connection to mongoose after every successful file write.
I am using a variable
var myFile = file.path (which is the file path from ng-file-upload) - after the successful write i have tried setting myFile to null to no avail.
It works when i switch views or refresh the page, but since im going for the single page app thing i would like to avoid this.....
here is my code on the server side:
/**
* Created by foolishklown on 8/27/2016.
*/
var mongoose = require('mongoose'),
path = require('path'),
Grid = require('gridfs-stream'),
fs = require('fs'),
User = require('../../models/user');
module.exports = function(file, userId, fileType, res) {
var fileId;
//console.log('called the write file for gridfs'.green);
//console.log('file is: ', file);
var conn = mongoose.createConnection('mongodb://localhost/media', (error) => {
if(error) {
console.error('Error connecting to mongod media instance'.red);
process.exit(1);
} else {
console.info('Connected successfully to mongod media instance in the write file!'.blue);
}
});
// The following line is designating a file to grab/read, and save into mongo
// in our case it will be something from ng-file-upload that the user wants to upload
var myFile = file.path;
// Connect gridFs and mongo
Grid.mongo = mongoose.mongo;
conn.once('open', function () {
console.log('connection open, ready for I/O!');
var gfs = Grid(conn.db);
// This write stream is how well write to mongo
var writeStream = gfs.createWriteStream({
// Name the file the way you want it stored in mongo
filename: file.originalFilename,
type: fileType
});
// Create a read stream, so that we can read its data, and then with that well use the
// write stream to write to the DB via piping the writestream
var readStream = fs.createReadStream(myFile)
.on('end', () => {
writeToUserDb(userId, fileType, readStream.id);
res.status(200).send({id: readStream.id, type: fileType, user: userId});
})
.on('error', () => {
res.status(500).send('error in writing with gridfs');
})
.pipe(writeStream);
//fs.createReadStream(myFile).pipe(writeStream);
writeStream.on('close', function (file) {
console.log(file.filename + 'written to DB');
/**
setTimeout(1000, () => {
fs.unlink(myFile);
});
*/
fs.unlink(myFile);
myFile = null;
conn.close();
});
});
function writeToUserDb(uid, type, fileId) {
var userConn = mongoose.createConnection('mongodb://localhost/mean-auth', (error) => {
if(error) {
console.error('Error connecting to the mean-auth instance'.red);
process.exit(1);
} else {
console.info('Connected to the mean-auth instance!'.blue);
console.info('Attempting to find user: ' + uid + ', filetype: ' + type + ', streamID: ' + fileId + '!'.green);
User.findById(uid, (err, doc) => {
if(err) {
console.error('Error finding user with id: ', uid);
process.exit(1);
} else {
console.log('original doc: ', doc);
doc.addMedia(type, fileId);
doc.save();
console.log('new doc: ', doc);
}
})
}
});
userConn.close();
}
};
alas, it was not an issue on the back end at all, it was an angular issue with ng-file upload.......
my html:
<div class="row">
<div class="col-lg-10">
<h1>MyPi Audio</h1>
</div>
<div class="col-lg-2">
<form name="form">
<input type="file" id="file1" name="file" ng-files="getTheFiles($files)"
ng-keep="false"
accept="'audio/*'">
<input type="button" class="btn btn-default" ng-click="uploadFiles('/dashboard/uploadAudio', 'audio', myCont.currentUser)" value="Upload">
</form>
</div>
</div>
<div class="row">
<div ng-repeat="audio in myCont.media.audio" style="width:100%;background-color:#999999;border:1px solid deeppink;">
<img ng-src="{{audio.url}}" />
<span>{{audio.name}}</span>
</div>
</div>
Inside the controller, building form data was not resetting......
the OLD code:
var formdata = new FormData();
$scope.getTheFiles = function ($files) {
angular.forEach($files, function (value, key) {
//console.log('key: ' + key + ', val: ' + $files[key]);
formdata.append(key, value);
});
}
};
After the response was sent back from the server, i simply called $scope.getTheFiles(null), and added a check for null conditions in the function which reset the form data
var formdata = new FormData();
$scope.getTheFiles = function ($files) {
if($files == null) {
formdata = new FormData();
} else {
angular.forEach($files, function (value, key) {
//console.log('key: ' + key + ', val: ' + $files[key]);
formdata.append(key, value);
});
}
};
I answered my question in case anyone else has the same issue in the future

Resources