javascript File to post function with $http angular service and web-api - javascript

I want to upload javascript fileor basically transmit a javascript file to post function, on client side I've used angularjs $http service to send data to client as shown below:
$http({
method: "POST",
url: "/api/fileupload",
data: JSON.stringify(scope.c.model),//scope.c.model is javascript File
contentType: "application/json"
}).then(successResponse => {
this.scope["text"] = "Succes...";
}, errorResponse=> {
this.scope["text"] = "Error...";
});
and here is web-api controller
public void Post(HttpPostedFile file)
{
//do stuff...
}
file is null but scope.c.model is filled with correct data. if I change the Type of data is transmitted to an array (for example), everything is fine..It seems that the post method does not recognize the file.
seocnd below way also does not work, file.count is zero.
public void Post()//HttpPostedFile file)
{
var httpRequest = HttpContext.Current.Request;
if (httpRequest.Files.Count > 0)
{
//do stuff...
}
}

Here is a solution for the problem..with code below I am totally able to save any file locally or on server.
client side
scope.c.model is the type of Javascript FILE API. behind the scene is the model which is like this ng-model = model , c is controller and becasue this code is in link function of my directive I can access the model trough scope.c.model . model here could be any name.
as I want to read the File I should use FileReader.
scope.$watch('c.model', () => {
if (scope.c.model != null) {
var reader = new FileReader();
reader.onload = () => {
var base64 = reader.result.split("base64,")[1];
var file =
{
content: base64,
name: scope.c.model.name,
type: scope.c.model.type,
size: scope.c.model.size
};
var t = file.content;
$http({
method: "POST",
url: "/api/fileupload",//web-api contorller
data: file,// scope.c.model is javascript File
contentType: "application/octet-stream"
}).then(successResponse => {
this.scope["text"] = "Succes...";
}, errorResponse=> {
this.scope["text"] = "Error...";
});
};
reader.readAsDataURL(scope.c.model);
}
});
server side
public class File
{
public string Content;
public string Name;
public string Type;
public string Size;
}
public class FileUploadController : ApiController
{
public void Post(File file)
{
var bytes = Convert.FromBase64String(file.Content);
using (var imageFile = new FileStream(#"C:\fileupload\"+file.Name + ".jpg", FileMode.Create))
{
imageFile.Write(bytes, 0, bytes.Length);
imageFile.Flush();
}
}
}

Related

Parameter Data Null Ajax to MVC Controller

Originally, I was passing one parameter to my MVC Controller via Ajax and it was working correctly. The parameter data was being received without any problems. However, I now need to pass an extra parameter and when I do this, neither parameter is sending data to the Controller? Thanks!
Ajax Code:
function uploadFile() {
var fileData = new FormData($(form1)[0]); //THIS IS A FILE UPLOAD
var details = JSON.stringify(markers); //MARKERS IS AN ARRAY
$.ajax({
url: '../Home/FilePost',
type: 'Post',
success: function (result) {
var newWindow = window.open('LasView?fileName=' + result, "", "new window");
},
error: function (xhr, status, error) {
alert(xhr.responseText);
},
xhr: function () { // Custom XMLHttpRequest
var myXhr = $.ajaxSettings.xhr();
if (myXhr.upload) { // Check if upload property exists
// TODO...
}
return myXhr;
},
error: function () { },
data: { filePost: fileData, googleMarkers: details },
cache: false,
contentType: false,
processData: false
});
}
My Controller:
[HttpPost]
public string LasPost(HttpPostedFileBase filePost, string googleMarkers){
return something;
}
My Array:
var markerObject = {
lat: marker.position.lat(),
lng: marker.position.lng()
};
markers.push(markerObject);
You cannot mix FormData and objects. You must .append() each name/value pair to the FormData instance.
Because you stringified your array, and are binding to a string googleMarkers parameter, then your code would need to be
function uploadFile() {
var fileData = new FormData($(form1)[0]); //THIS IS A FILE UPLOAD
var details = JSON.stringify(markers); //MARKERS IS AN ARRAY
fileData.append('googleMarkers', details); // append the name/value pair
$.ajax({
....
data: fileData, // send only the FormData instance
....
});
})
However you should be taking advantage of MVC's model binding features and posting data which binds to a model representing your coordinates, for example
public class Coordinate
{
public double Latitude { get; set; }
public double Longitude { get; set; }
}
and the POST method would then be
[HttpPost]
public string LasPost(HttpPostedFileBase filePost, IEnumerable<Coordinate> googleMarkers)
and to send that data
var fileData = new FormData($(form1)[0]);
for(var i = 0; i < markers.length; i++)
{
fileData.append('[' + i + '].Latitude', markers[i].lat);
fileData.append('[' + i + '].Longitude', markers[i].lng);
}
$.ajax({
....
data: fileData,
....
});

SpringBoot / Fetch : Invalid mime type "undefined": does not contain '/'

I'm trying to make a post request with a form data, containing a file and a Json Object.
To perform this, i set the Content-Type to undefined, according to the following post
https://stackoverflow.com/a/25183266/4573767
This causes the browser to set the Content-Type to multipart/form-data
and fill the boundary correctly.
However, on the (springboot) server side, i get this error message :
Resolved exception caused by Handler execution:
org.springframework.web.HttpMediaTypeNotSupportedException: Invalid
mime type "undefined": does not contain '/'
So, it seems that the "undefined" content type is not correctly managed by the browser.
Here is the fetch command, on the client side :
// My document blob
var documentBlob = new Blob([JSON.stringify({ documentName: "toto" })], {
type: "application/json"
});
// My Form data containing a file and the document blob
var formData = new FormData();
formData.append("file", this.state.file);
formData.append("document", documentBlob);
// Fetch command
fetch("/document/", {
method: "POST",
headers: {
"Content-Type": undefined
},
data: formData
}).then(function(response) {
console.log("response!");
});
Here is the server side (spring boot rest controller) :
#RestController
#RequestMapping("/document")
public class DocumentController {
#Autowired
private DocumentRepository documentRepository;
#RequestMapping(value = "/", method = RequestMethod.POST, consumes = { "multipart/form-data" })
public boolean addDocument(#RequestPart("document") Document document, #RequestPart("file") MultipartFile file) {
documentRepository.save(document);
return true;
}
}
"Document" is a simple pojo :
#Entity
public class Document {
private String documentName;
public Document() {
}
public Document(String documentName) {
this.setDocumentName(documentName);
}
public String getDocumentName() {
return documentName;
}
public void setDocumentName(String documentName) {
this.documentName = documentName;
}
}
So, i don't really get if the problem is in the client or server side.
Thanks!
//////////////////////////////
EDIT :
I finally got it working, but using axios instead of fecth:
Here is my finaly spring boot rest controller :
#RequestMapping(value = "/", method = RequestMethod.POST)
public boolean addDocument(#RequestPart("document") Document document, #RequestPart("file") MultipartFile file) {
// Do things!
return true;
}
And my javascript/axios call :
var documentBlob = new Blob([JSON.stringify({ documentName: "test" })], {
type: "application/json"
});
var formData = new FormData();
formData.append("document", documentBlob);
formData.append("file", this.state.file);
axios({
method: "post",
url: "/document/",
data: formData,
config: { headers: { "Content-Type": "multipart/form-data" } }
})
.then(response => {
console.log("it's working!");
console.log(response);
})
.catch(function(error) {
console.log(error);
});
I finally got it working, but using axios instead of fecth.
See the edited original post to see my solution.
I think the issue is in your spring controller request mapping.
You should not have the mapping to / there.
Try this...
#RestController
#RequestMapping("/document")
public class DocumentController {
#Autowired
private DocumentRepository documentRepository;
#RequestMapping(method = RequestMethod.POST, consumes = { "multipart/form-data" })
public boolean addDocument(#RequestPart("properties") Document document, #RequestPart("file") MultipartFile file) {
documentRepository.save(document);
return true;
}
}
Have you tried to make that request with the "multipart/form-data" content type header?
With that mapping method consuming the defined header, your controller won't be able to parse the request without the proper content type.

How to Upload Files using ajax call in asp.net?

I have created a small asp.net web forms application, to manage emails , i have created a little interface contains mandatory information to send a email, like from , to , subject etc. now i want to attach files to the email, i have used asp.net file upload controller to upload files,
and have to attach multiple files,
Now i want to send this details to code behind, so i thought the best way is to use ajax calls , because i don't want to refresh my page, but i can't figure out the way how to send the attached files to the server side,
i have read some articles and they saying i have to use FormData to send the files ,
then i have created a FormData object and appended all the attached files to the object.but how to pass this object to server side,
my js code as below,
function sendEmail() {
var data = new FormData();
var files = $('.attachment');
$.each(files, function (key, value) {
var file = $(value).data('file');
data.append(file.name, file);
});
$.ajax({
url: "OpenJobs.aspx/sendEmail",
type: "POST",
async: false,
contentType: false, // Not to set any content header
processData: false, // Not to process data
data: null,
success: function (result) {
alert(result);
},
error: function (err) {
alert(err.statusText);
}
});
}
Any help?
You need to use Generic handler to upload files using ajax, try below code:
function sendEmail() {
var formData = new FormData();
var files = $('.attachment');
$.each(files, function (key, value) {
var file = $(value).data('file');
formData.append(file.name, file);
});
$.ajax({
url: "FileUploadHandler.ashx",
type: "POST",
contentType: false, // Not to set any content header
processData: false, // Not to process data
data: formData,
success: function (result) {
alert(result);
},
error: function (err) {
alert(err.statusText);
}
});
}
Generic handler
<%# WebHandler Language="C#" Class="FileUploadHandler" %>
using System;
using System.Web;
public class FileUploadHandler : IHttpHandler
{
public void ProcessRequest (HttpContext context)
{
if (context.Request.Files.Count > 0)
{
HttpFileCollection files = context.Request.Files;
for (int i = 0; i < files.Count; i++)
{
HttpPostedFile file = files[i];
string fname = context.Server.MapPath("~/uploads/" + file.FileName);
file.SaveAs(fname);
}
context.Response.ContentType = "text/plain";
}
}
}

How to print receipt without print dialog box in client side

I want print receipt in client side without print dialog box, i am using mvc this is my solution to achieve my problem.
EPSON printer was installed in my system.This solution is working when host in my local iis but its not work when host in server and accessing from my local system getting "An error occurred while processing your request" error. In server no printer is installed.
$.ajax({
type: "POST",
url: '../Service/print',
cache: false,
data: { iprintData: printData, iprinterName: sPrinterName },
success: function (data) {
// alert('print Send Successfully');
},
error: function (ex) {
alert(ex.responseText);
// alert('error while Seding print');
}
});
this is my code in controller
public JsonResult print(string iprintData, string iprinterName)
{
Boolean bflag = false;
System.Web.HttpContext.Current.Session["_printData"] = iprintData;
PrintDocument printDocument = new PrintDocument();
printDocument.PrintController = new StandardPrintController();
printDocument.PrintPage += PrintDocumentOnPrintPage;
printDocument.PrinterSettings.PrinterName = iprinterName;
//printFont = new System.Drawing.Font("Arial", 10);
printDocument.Print();
bflag = true;
return Json(bflag, JsonRequestBehavior.AllowGet);
}
public static Image resizeImage(Image image, int new_height, int new_width)
{
Bitmap new_image = new Bitmap(new_height, new_width);
Graphics g = Graphics.FromImage((Image)new_image);
g.InterpolationMode = InterpolationMode.High;
g.DrawImage(image, 0, 0, new_width, new_height);
return new_image;
}
private void PrintDocumentOnPrintPage(object sender, PrintPageEventArgs e)
{
string printstring = System.Web.HttpContext.Current.Session["_printData"].ToString();
string path = HttpContext.Server.MapPath("~/content/Images/logo.png");
System.Drawing.Image img = Image.FromFile(path);
//img = resizeImage(img, 80, 60);
e.Graphics.DrawImage(img, 6, 100);
e.Graphics.DrawString(printstring, new System.Drawing.Font("ronnia", 9), Brushes.Black, 10, 150);
}
can any one help me from this ?
first you have to write windows service that contain HttpListener.
write your printing code inside the service
Install the service in client machine
call that service using ajax like below.
function PrintReceipt() {
var PrintData = JSON.parse($("#receiptData").html())
if (PrintData.length > 0) {
$.ajax({
type: "POST",
url: "http://localhost:41963/printOrder",
data: JSON.stringify({ "PrintData": PrintData }), //reciept data
crossDomain: true,
success: function (response) {
},
error: function () {
}
});
}
}
set System.Drawing.dll property
Copy Local=true

Download CloudBlockBlob as savable file to a browser from .Net MVC 6

I'm trying to provide a browser user the ability to select a file from a list an download a file back to the user as a file download.
My JavaScript looks like this:
$scope.getFile = function (podUri, podName) {
$http.get('api/getDharmaPod', { params: { containerName: $scope.selectedContainer, podName: podName } })
.success(function (data, status, headers, config) {
$("#audio").text("Got file: ");
})
.error(function (data, status, headers, config) {
alert("got an error:" + status);
});
};
I've also tried the following that I found on stackOverflow
$scope.getFile = function (podUri, podName) {
$http({
method: 'GET',
params: { containerName: $scope.selectedContainer, podName: podName },
cache: false,
url: 'api/getDharmaPod',
headers: {
'Content-Type': 'audio/mpeg; charset=utf-8'
}
}).success(function (data, status) {
console.log(status);
}).error(function (data, status) {
alert("got an error:" + status);
});
};
But the result is the same: the browser silently receives the server's transmission and doesn't offer to save it anywhere.
My MVC controller method looks like this:
[HttpGet, Route("api/getDharmaPod")]
public async Task<HttpResponse> GetDharmaPod(string containerName, string podName)
{
var dharmaBlob = AzureStorageAccess.GetBlob(containerName, podName);
MemoryStream memStream = new MemoryStream();
dharmaBlob.DownloadToStream(memStream);
Response.ContentType = "audio/mpeg";
await Response.SendAsync(memStream.ToArray());
return null;
}
I've also tried:
[HttpGet, Route("api/getDharmaPod")]
public FileResult GetDharmaPod(string containerName, string podName)
{
var dharmaBlob = AzureStorageAccess.GetBlob(containerName, podName);
MemoryStream memStream = new MemoryStream();
dharmaBlob.DownloadToStream(memStream);
Response.ContentType = "audio/mpeg";
return File(memStream.ToArray(), "audio/mpeg", podName);
}
Again the browser receives the data but doesn't see it as a file to be stored. It just receives it into a variable. I'd want it to see it as a download and save it to the download file.
I'm not sure if I'm sending it incorrectly or receiving it incorrectly or both :-(
Thanks for any guidance.
I've decided to go another way since I can't seem to find a solution.
My solution is to just download the file directly from the container using the blob's url. I've made it somewhat secure by generating a shared access key in my controller as follows:
public static string GetSharedAccessKey(string containerName)
{
CloudStorageAccount storageAccount = GetAccount(_useDev);
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference(containerName);
SharedAccessBlobPolicy blobPolicy = new SharedAccessBlobPolicy
{
Permissions = SharedAccessBlobPermissions.Read,
SharedAccessExpiryTime = DateTime.UtcNow.AddHours(1)
};
return container.GetSharedAccessSignature(blobPolicy);
}
this returns an access key that can be appended to the 'a' tag's href link for the blob file that allows access for one hour.
I'm now getting a file that the browser is storing in the downloads directory as expected.
The result of allowing direct access to the storage account is also more efficient for the server-side app.

Categories

Resources