I'm trying to upload files using Angularjs for REST API exposed via Spring :
This is my Controller:
#RequestMapping(value = util/images/{partyId},
method = RequestMethod.POST)
public JsonNode uploadPartyRefImage(#RequestPart("file") MultipartFile inputFile,
#PathVariable String partyId){
ObjectMapper objectMapper = new ObjectMapper();
JsonNode jNode = null;
try {
String[] fileInput = ((DiskFileItem) ((CommonsMultipartFile) inputFile).getFileItem()).getName().split("\\.");
Path storagePath= Paths.get(uploadPath);
FileSystemUtil.writeFile(storagePath,inputFile.getInputStream());
jNode = objectMapper.readTree("{\"type\":\"" + "success" + "\",\"fileStorePath\":\"" + pathString + "\"}");
} catch (Exception exApi) {
LOGGER.error("Error uploading Party attached Image "+ exApi);
}
return jNode;
}
This API works fine when used via Postman. The Postman call:
But when calling through angular it throws Exception:
Angular service:
function uploadImage(formData,partyRefId){
console.log(utilService);
if (utilService) {
return utilService.request({
method: "POST",
resource: "/images/" + partyRefId,
headers: { 'Content-Type': undefined},
processData: false,
transformRequest: angular.identity,
mimeType: "multipart/form-data",
cache: false,
data: formData
})
.then(function (data) {
if (data) {
return getResultDataFromResponse(data);
}
}, function (error) {
console.log('error invoking document upload service', error);
});
}
}
Angular Controller:
$ctrl.uploadDocument = function () {
var formData = new FormData();
formData.append("file", k.documentfile.lfFile);
var fileName = "PARTY01" + k.documentReference;
fbeOnboardingWizardService.uploadImage(formData,fileName)
.then(function (data) {
if(data.type == "success")
console.log(data.fileStorePath);
},function (error) {
console.log(error);
});
};
Error in Jboss:
02:06:25,442 WARN [org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver] (http--0.0.0.0-8080-4) Handler execution resulted in exception: Content type 'null' not supported
If I update the Content-Type to "multipart/form-data" in angular service
Error in Jboss:
Servlet.service() for servlet appServlet threw exception: org.apache.commons.fileupload.FileUploadException: the request was rejected because no multipart boundary was found
Related
I am trying to upload 3 photos from frontend using formData. It will call an external API to make the upload. But encountered some errors as below.
Frontend upload
const formData = new FormData()
formData.append('photoA', this.photoA)
formData.append('photoB', this.photoB)
formData.append('photoC', this.photoC)
axios.post(`http://localhost:4172/uploadDocs`,
{
data: formData,
accessToken: store.state.token
},
{ headers: {
// 'Content-Type': 'Application/json',
// 'x-access-token': localStorage.getItem('token')
}
}
).then (function (response) {
return response.data
})
Nodejs upload API
async uploadDocs (req, res) {
const options = {
method: "POST",
url: "https://example.com/api/v1/users/uploadDocuments?access_token=" + req.body.accessToken,
headers: {
//"Authorization": "Basic " + auth,
//"Content-Type": "multipart/form-data"
},
data: req.body.data
};
try {
request(options, function (err,response,body){
if (err) {
res.send(err)
} else {
res.send(response.body)
}
})
} catch (error) {
res.status(400).send({
error: "Server error."
})
}
}
So there are 2 errors here:
a) Frontend error: It keeps giving Cannot POST / error in html
b) Backend error:
<h1>Cannot read property 'photoA' of undefined</h1>
<h2></h2>
<pre></pre>
Been struggling with this for days. Any help will be very much appreciated.
I am doing a simple function to update a field in the database and I get this error:
Failed to load resource: the server responded with a status of 403 (Forbidden)
I do the request in html/Jquery:
function AgregarLike(id, num){
alert("Entre:" + id);
var urlAction = "#Url.Action("UpdateLikeVisitBrandPhoto", "Report")";
alert (urlAction);
var request;
// Fire off the request to /form.php
request = $.ajax({
url: urlAction + '/' + id,
type: "post"
});
// Callback handler that will be called on success
request.done(function (response, textStatus, jqXHR){
// Log a message to the console
console.log("Hooray, it worked!");
console.log(response);
console.log(textStatus)
alert("worked");
});
}
And the controller (I return all the time bu.CreateLike(Id) because I want to forze the error):
public int UpdateLikeVisitBrandPhoto(int id)
{
try
{
try
{
var num = bu.CreateLike(id);
}
catch
{
return bu.CreateLike(id);
}
return bu.CreateLike(id);
}
catch (ServicesException ex)
{
logger.Error("", ex);
Console.WriteLine(ex);
return bu.CreateLike(id);
}
catch (Exception ex)
{
logger.Error("", ex);
Console.WriteLine(ex);
return bu.CreateLike(id);
}
}
And the model:
public int CreateLike(int id)
{
using (var sqlConnection = DatabaseUtilities.GetConnection())
{
var SQL = "UPDATE [RBAcuerdos].[dbo].[VisitBrandPhoto] SET MeGusta = 1 WHERE id = #paramId";
var sqlCommand = new SqlCommand(SQL, sqlConnection);
sqlCommand.Parameters.Add(new SqlParameter("paramId", id));
//sqlCommand.Parameters.Add(new SqlParameter("paramvalue", 1));
return sqlCommand.ExecuteNonQuery();
}
//throw new NotImplementedException();
}
Someone can help me please?
Since you're sending a POST request, the parameters you need to send should not be a part of the URL. Try sending the parameters like:
request = $.ajax({
url: urlAction,
data: {id: id},
type: "POST",
contentType: 'application/json; charset=utf-8',
success: function (data) {
alert("It worked!");
},
error: function () {
alert("Error");
}
});
Further Reading:
How to pass parameters in $ajax POST?
request = $.ajax({
url: urlAction + '?id=' + id,
type: "get"
});
Substitute your code
var urlAction = "#Url.Action("UpdateLikeVisitBrandPhoto", "Report")";
It generates
/Report/UpdateLikeVisitBrandPhoto
To hit controller you need your url to be
/Controller/Action?param1=paramvalue //single param
/Controller/Action?param1=paramvalue ¶m2=paramvalue //multiple params,apppend each paramname with prefix &
I am working Angular SPA application.
I am using SP.js & SP.Requestor.js which is useful to upload the same but none seems to be working of Angular 4 App.
UploadFile(event: any) {
let fileList: FileList = event.target.files;
let fileName;
if (fileList.length != 0) {
this.getFileBuffer(fileList[0]).then(result => {
this.uploadFile(result, fileList[0].name, "POC").then(result => {
alert("added");
});
});
// this.fileUpload(fileList[0], "RetrievePOC", fileList[0].name);
}
}
getFileBuffer(file) {
return new Promise((resolve, reject) => {
var myReader: FileReader = new FileReader();
myReader.onload = function (e) {
resolve(myReader.result);
//resolve(e.target);
}
myReader.onerror = function (e) {
//deferred.reject(e.target.error);
}
//myReader.readAsArrayBuffer(file);
myReader.readAsBinaryString(file);
//resolve(file);
//return deferred.promise();
});
};
uploadFile(file, fileName, libraryName) {
return new Promise((resolve, reject) => {
// Construct the endpoint - The GetList method is available for SharePoint Online only.
//var serverRelativeUrlToFolder = "decodedurl='" + "/" + libraryName + "'";
var endpoint = this.siteUrl + "/_api/web/lists/getByTitle('POC')/Files/add('" + fileName + "')";
const headers = {
"accept": "application/json;odata=verbose",
"content-type": "application/json; odata=verbose",
};
//let fileData =this.convertDataBinaryString(file);
this.executeAsync(endpoint, file, headers).then(file => resolve(true)).catch(err => reject(err));
});
}
executeAsync(endPointUrl, data, requestHeaders) {
return new Promise((resolve, reject) => {
// using a utils function we would get the APP WEB url value and pass it into the constructor...
let executor = new SP.RequestExecutor(this.siteUrl);
// Send the request.
executor.executeAsync({
url: endPointUrl,
method: "POST",
body: data,
binaryStringRequestBody: true,
headers: requestHeaders,
success: offset => resolve(offset),
error: err => reject(alert(err.responseText))
});
});
}
Getting following error in executeAsync methond :
ErrorPage.PostMessage: Origin=https://localhost:44316,
Data={"command":"Query","postMessageId":"SP.RequestExecutor3","responseAvailable":false,"errorCode":-1007,"errorMessage":"Correlation
ID: e12d5a9e-b0d6-0000-745f-24b31dd971a6"}
vendor.js?v=T82_qgC1tKr4vAoag-4pr9ch_dUDSit3nEgaqP4H0Ec:12090 ERROR
Error: Uncaught (in promise): undefined
at resolvePromise (vendor.js?v=T82_qgC1tKr4vAoag-4pr9ch_dUDSit3nEgaqP4H0Ec:87020
)
We can use jQuery to upload file, here is a demo for your reference:
HTML:
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.9.1.min.js" type="text/javascript"></script>
<input id="getFile" type="file"/><br />
<input id="displayName" type="text" value="Enter a unique name" /><br />
<input id="addFileButton" type="button" value="Upload" onclick="uploadFile()"/>
JS code:
'use strict';
jQuery(document).ready(function () {
// Check for FileReader API (HTML5) support.
if (!window.FileReader) {
alert('This browser does not support the FileReader API.');
}
});
// Upload the file.
// You can upload files up to 2 GB with the REST API.
function uploadFile() {
// Define the folder path for this example.
var serverRelativeUrlToFolder = '/shared documents';
// Get test values from the file input and text input page controls.
var fileInput = jQuery('#getFile');
var newName = jQuery('#displayName').val();
// Get the server URL.
var serverUrl = _spPageContextInfo.webAbsoluteUrl;
// Initiate method calls using jQuery promises.
// Get the local file as an array buffer.
var getFile = getFileBuffer();
getFile.done(function (arrayBuffer) {
// Add the file to the SharePoint folder.
var addFile = addFileToFolder(arrayBuffer);
addFile.done(function (file, status, xhr) {
// Get the list item that corresponds to the uploaded file.
var getItem = getListItem(file.d.ListItemAllFields.__deferred.uri);
getItem.done(function (listItem, status, xhr) {
// Change the display name and title of the list item.
var changeItem = updateListItem(listItem.d.__metadata);
changeItem.done(function (data, status, xhr) {
alert('file uploaded and updated');
});
changeItem.fail(onError);
});
getItem.fail(onError);
});
addFile.fail(onError);
});
getFile.fail(onError);
// Get the local file as an array buffer.
function getFileBuffer() {
var deferred = jQuery.Deferred();
var reader = new FileReader();
reader.onloadend = function (e) {
deferred.resolve(e.target.result);
}
reader.onerror = function (e) {
deferred.reject(e.target.error);
}
reader.readAsArrayBuffer(fileInput[0].files[0]);
return deferred.promise();
}
// Add the file to the file collection in the Shared Documents folder.
function addFileToFolder(arrayBuffer) {
// Get the file name from the file input control on the page.
var parts = fileInput[0].value.split('\\');
var fileName = parts[parts.length - 1];
// Construct the endpoint.
var fileCollectionEndpoint = String.format(
"{0}/_api/web/getfolderbyserverrelativeurl('{1}')/files" +
"/add(overwrite=true, url='{2}')",
serverUrl, serverRelativeUrlToFolder, fileName);
// Send the request and return the response.
// This call returns the SharePoint file.
return jQuery.ajax({
url: fileCollectionEndpoint,
type: "POST",
data: arrayBuffer,
processData: false,
headers: {
"accept": "application/json;odata=verbose",
"X-RequestDigest": jQuery("#__REQUESTDIGEST").val(),
"content-length": arrayBuffer.byteLength
}
});
}
// Get the list item that corresponds to the file by calling the file's ListItemAllFields property.
function getListItem(fileListItemUri) {
// Send the request and return the response.
return jQuery.ajax({
url: fileListItemUri,
type: "GET",
headers: { "accept": "application/json;odata=verbose" }
});
}
// Change the display name and title of the list item.
function updateListItem(itemMetadata) {
// Define the list item changes. Use the FileLeafRef property to change the display name.
// For simplicity, also use the name as the title.
// The example gets the list item type from the item's metadata, but you can also get it from the
// ListItemEntityTypeFullName property of the list.
var body = String.format("{{'__metadata':{{'type':'{0}'}},'FileLeafRef':'{1}','Title':'{2}'}}",
itemMetadata.type, newName, newName);
// Send the request and return the promise.
// This call does not return response content from the server.
return jQuery.ajax({
url: itemMetadata.uri,
type: "POST",
data: body,
headers: {
"X-RequestDigest": jQuery("#__REQUESTDIGEST").val(),
"content-type": "application/json;odata=verbose",
"content-length": body.length,
"IF-MATCH": itemMetadata.etag,
"X-HTTP-Method": "MERGE"
}
});
}
}
// Display error messages.
function onError(error) {
alert(error.responseText);
}
So, I am trying to generate PDF file by passing the HTML string to the server to generate the byte streams using NReco library http://www.nrecosite.com/pdf_generator_net.aspx and return it back to the client side however, after I converted to blob format and save it with FileSaver library https://github.com/eligrey/FileSaver.js/, the saved file is unable to open.
Below are my code by far:
controller
string HtmlContent = model.HtmlContent;
string PageType = gradeReportPdfBindingModel.PageType;
string FileName = gradeReportPdfBindingModel.FileName;
var pdfDoc = new HtmlToPdfConverter();
if (string.IsNullOrEmpty(PageType))
pdfDoc.Orientation = PageOrientation.Default;
else
{
if (PageType == "Landscape")
pdfDoc.Orientation = PageOrientation.Landscape;
else
pdfDoc.Orientation = PageOrientation.Portrait;
}
var pdfBytes = pdfDoc.GeneratePdf(HtmlContent);
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
result = Request.CreateResponse(HttpStatusCode.OK);
result.Content = new ByteArrayContent(pdfBytes);
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentDisposition.FileName = FileName;
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
return result;
Customer.js
Customer.Export(exportModel).then(function (response) {
var file = new Blob([response.data], { type: 'application/pdf' });
saveAs(file, fileName);
});
HTTP POST call
Export: function (model) {
return $http({
method: 'POST',
headers: {
accept: 'application/pdf'
},
url: appSettings.serverPath + '/customer/export',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
data: $.param(model),
});
},
Response log from browser console:
Object { data: "%PDF-1.4 1 0 obj << /Title (��) /Cr…", status: 200, headers: ed/<(), config: Object, statusText: "OK" }
Edit 1:
I tried to return the result as HttpResponseMessage. How can I consume it on javascript side?
Edit 2:
I figured it out. This is how I do it.
Controller:
[HttpPost]
[Route("export")]
public IHttpActionResult GeneratePdf(model)
{
var pdfBytes = pdfDoc.GeneratePdf(HtmlContent);
var policy = new CacheItemPolicy { AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(300), Priority = CacheItemPriority.NotRemovable };
var cacheId = Guid.NewGuid().ToString();
MemoryCache.Default.Add("pdfBytes_" + cacheId, pdfBytes, policy);
return Ok(cacheId);
}
[Authorize]
[HttpGet]
[Route("getPdf/{cacheId}/{fileName}")]
public HttpResponseMessage DownloadPdf(Guid CacheId, string FileName)
{
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
try
{
var pdfBytes = (Byte[])MemoryCache.Default.Get("pdfBytes_" + CacheId);
MemoryCache.Default.Remove("pdfBytes_" + CacheId);
using (MemoryStream memorystream = new MemoryStream(pdfBytes))
{
response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new ByteArrayContent(memorystream.ToArray());
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentDisposition.FileName = FileName;
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
return response;
}
}
customer.js:
Customer.Export(model).then(function (response) {
Customer.DownloadPdf(response.data, fileName).then(function (response) {
var file = new Blob([response.data], { type: "application/pdf" });
saveAs(file, fileName);
}).catch(function (response) {
console.error('Error', response.status, response.data);
});
});
Http calls:
Export: function (model) {
return $http({
method: 'POST',
url: appSettings.serverPath + '/customer/export',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
data: $.param(model),
});
},
DownloadPdf: function (cacheId, fileName) {
return $http({
method: 'GET',
headers: {
accept: 'application/pdf'
},
responseType: 'arraybuffer',
url: appSettings.serverPath + '/customer/downloadPdf/' + cacheId + '/' + fileName,
headers: { 'Content-Type': 'application/pdf' }
});
}
I basically tested it on my local dev machine and it works, but when I published it Azure Web App, I was unable to get through the POST call and it returns status 500 after some time. Not sure why, but I am suspecting the MemoryCache I am using. Any idea will be appreaciated.
Thanks.
i use node.js as server and android as client, the server work normally send and receive data from client (except android)
here my code in javascript
function put(id, data, callback) {
$.ajax('http://mydomain.com:8888/' + id + '/', {
type: 'POST',
data: JSON.stringify(data),
dataType: 'json',
success: function(data) {
if (callback)
callback(data);
},
error: function() {
if (callback)
callback(false);
}
});
}
and my node script
function handler ( req, res ) {
if ( req.method === 'POST' ) {
console.log('receive data from post');
}
}
the code above has successfully sent data.
i want to send data (post) to node (like what javascript does) in android?
how i achieve that?
thanks
But of course
Here you go
public void postData() {
// Create a new HttpClient and Post Header
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://www.yoursite.com/script.php");
try {
// Add your data
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("id", "12345"));
nameValuePairs.add(new BasicNameValuePair("stringdata", "AndDev is Cool!"));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
// Execute HTTP Post Request
HttpResponse response = httpclient.execute(httppost);
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
} catch (IOException e) {
// TODO Auto-generated catch block
}
}