DropZone.js server side validation - javascript

I'm doing server side validation for the files uploaded. Not every file that makes it to the server is stored. How can I display/trigger the error on the file(s) that were not successfully stored on the server. I've tried adding a server Validation function but can't figure out how to do it... Please help
this.on("successmultiple", function (file, successResponse) {
uploadResult = eval(successResponse);
toastr.options.positionClass = "toast-bottom-right";
var ErrorMessage = "";
for (var i = 0; i < uploadResult.ResultList.length; i++) {
var result = uploadResult.ResultList[i];
if (result.IsSuccessful === "True") {
toastr.success(result.Message);
if (hdnFileIDList !== "")
hdnFileIDList = hdnFileIDList + "|" + result.ID;
else
hdnFileIDList = result.ID
}
else {
//-- trigger dropzone error
toastr.warning(result.Message);
//this.ValidationError(file, result.Message);
file.accepted = false;
file.status = Dropzone.ERROR;
dropzone.serverError(file, result.Message);
//dropzone.emit("errormultiple", file, result.Message);
}
}
$("#<%=hdnSharedFileObjNewFileIDList.clientID%>").val(hdnFileIDList);
});

Solved my problem by adding the following code to Dropzone.js then calling it from my "successmultiple" event when I see and error in my returned JSON from the server.
Dropzone.prototype.serverError = function (file, message) {
file.accepted = false;
file.status = Dropzone.ERROR;
return this._errorProcessing(file, message);
};

To anyone else that's landed here after searching for a solution to this problem: there's a pretty simple and elegant way to deal with this without getting into the guts of Dropzone. If your server side validation fails, return a status code of 400 (bad request) and include your error message as a jsonResponse.
Then you can handle the response with something like the following code in your dropzone's init configuration (assuming you are sending your error message as "ValidationMessage"):
this.on("error", function (file, jsonResponse) {
var errorMessage = "Could not upload document: ";
if (jsonResponse["ValidationMessage"] != null) {
errorMessage += jsonResponse["ValidationMessage"];
} else {
errorMessage += "unknown error";
}
alert(errorMessage);
});
The file will have a big red X on it just like a regular Dropzone failed upload.
This solution is for single uploads rather than multiple but the same idea should work for multiple.

Related

How to send data through URL via Google Scripts

I am trying to send email addresses from a google sheet to an external web page via Google Scripts, but it doesn't seem to be working.
From reading other similar issues it seems that I need the doPost() function but I'm unsure how I should incorporate it into my script.
Here's my google script
function getEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var data = sheet.getDataRange().getValues();
var myUrl = 'https://my.url/';
if(data) {
for(var i = 0; i < data.length; i++) {
if(i !== 0) {
postToForm(myUrl, data[i][0]);
}
}
deleteData(sheet, data);
}
}
function postToForm(url, data) {
UrlFetchApp.fetch(url + 'user/add/?email=' + data);
}
function deleteData(sheet, data){
for (var i = data.length; i>1; i--) {
sheet.deleteRow(i);
}
}
and here is the receiving script:
<script>
window.addEventListener('DOMContentLoaded', async () => {
if (location.search) {
const urlSearchParams = location.search;
try {
await DB.ready();
const email = getUrlParameter('email', urlSearchParams);
if (email) {
emailSignUp(email)
return;
}
} catch (error) {
console.log(error);
showSnackBar('Something went wrong', false);
return;
}
}
showSnackBar('Something went wrong', false);
});
function getUrlParameter(key, urlSearchParams) {
key = key.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
var regex = new RegExp('[\\?&]' + key + '=([^&#]*)');
var results = regex.exec(urlSearchParams);
return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
}
</script>
Maybe I need to change the postToForm function to doPost and add it that way?
Thanks
Answer
On one hand there is UrlFetchApp, it is designed to fetch resources and communicate with other hosts over the Internet. On the other hand there is, doPost that runs when an HTTP POST request is sent to a web app. It is developed by the user using Google Apps Script and publishing the script as web app.
In your case, as you are calling an external web, you need to use UrlFetchApp in a proper way. In the documentation there are two examples that show how to make the HTTP request, however your case looks different. Usually, when you make an HTTP POST request to send data to a server, you put that data on the message body request but depending on the design of your API, you can send data through the query component of the URI.
In your case, the code will look like this:
function postToForm(url, data) {
var uri = url + 'user/add/?email=' + data
var options = {
'method' : 'post',
'payload' : ''
};
UrlFetchApp.fetch(uri, options);
}

Retrieve and access value from Tizen's scope outside synchronously

May be I am not asking it in right way. I am kind of new on Tizen.
Here is my code set for tizen.
respons = tizen.filesystem.resolve("documents", function(dir)
{
file = dir.resolve("myfile.txt");
if(file.isFile){ //if file is present then fetch the information.
var res_one = file.openStream("r",
function(fs) {
var my_json = JSON.parse(fs.read(file.fileSize));
fs.close();
res_two = my_json.json_value;
return res_two;
},
function(e) {
console.log("Error " + e.message);
return null;//if there is any error then return null
}, "UTF-8");
return res_one;
}
else{
return null; //if file is not present then return null
}
});
Basically I have a file present on my display(Installed Tizen OS) that contains a json:
json_value: "My Information"
I am trying to fetch the information to use that in my javascript code. I am able to fetch that information(Checked using console.log). But it is not being returned in res_one or in response.
In short form I want to access that json outside tizen.filesystem.resolve( ...
Thanks in advance.
I have done it. Basically this is asynchronous behaviour of javascript so I have done it using call back.
function to_fetch_the_value_and_chain_process(passed_function){
tizen.filesystem.resolve("documents", function(dir){
file = dir.resolve("myfile.txt");
if(file.isFile){ //if file is present then fetch the information.
var res_one = file.openStream("r",
function(fs) {
var my_json = JSON.parse(fs.read(file.fileSize));
fs.close();
res_two = my_json.json_value;
passed_function(res_two);
},
function(e) {
console.log("Error " + e.message);
passed_function(null);;//if there is any error then return null
}, "UTF-8");
return res_one;
}
else{
passed_function(null); //if file is not present then return null
}
});
}
funtion passed_function(retrieve_res_two){
alert(retrieve_res_two );
//use retrieve_res_two and chain the next code here.....
}
to_fetch_the_value_and_chain_process(passed_function);

Response for FileUploader's uploadComplete-Event is undefined

I'm developing a SAPUI5 app and use the FileUploader control in my app to upload documents to a server. The uploading works and I also receive a response from the server (I can see this in the DevTools of Chrome).The problem is that the event-object inside the 'uploadComplete' event-handler always returns undefined for the response parameter.
Do you know why this is the case and how I can fix it?
Here is the initialization of the FileUploader:
var oFileUploader = new sap.ui.unified.FileUploader({
uploadUrl: "/fileupload",
name: "documentUploader",
uploadOnChange: false,
multiple: false,
width: "400px",
uploadComplete: this.onDocumentUploadComplete
});
And here is the 'uploadComplete' event-handler:
onDocumentUploadComplete: function(oEvent) {
var response = oEvent.getParameter("response");
console.log(response); // response = undefined
}
I still haven't figured out how to receive the server's response but I have found a workaround.After uploading the file I just send a request to the server and tell it to check whether the file exists.If it exists the server returns "true" and if it doesn't the server returns "false". Here's my code:
// eventhandler for the "uploadComplete"-event of the FileUploader-control
onDocumentUploadComplete: function(oEvent) {
var uploaderControl = oEvent.getSource();
var documentname = uploaderControl.getValue();
var fileURI = "/file/" + documentname + "?exists";
$.get(fileURI, function(data) {
if (data === "true") {
console.log("Successfully uploaded: " + documentname);
this.handleDocumentUploadSuccess(documentname);
} else {
console.log("Error when uploading document: " + documentname);
this.handleDocumentUploadError(documentname);
}
}.bind(this));
}
According to the documentation the parameter response is subject to some conditions.
Response message which comes from the server. On the server side this
response has to be put within the "body" tags of the response document
of the iFrame. It can consist of a return code and an optional
message. This does not work in cross-domain scenarios.
That means the response fom the server must be XML or HTML.

Blueimp jQuery File Upload and my exception

I want to pass error message to Blueimp jQuery File Upload plugin. I use ASP.NET MVC and throw my own exception when some conditions are appeared (i.e. file is not real image, only image exception or image is too wide etc).
var file = Request.Files[i];
_service.ImageValidation(file.InputStream);
public void ImageValidation(System.IO.Stream fileStream)
{
Bitmap bmp = null;
try
{
bmp = new Bitmap(fileStream, false);
}
catch
{
throw new NoImageException();
}
if (bmp.Width > bmp.Height && (bmp.Width < 1024 || bmp.Height < 768))
throw new ImageDimensionTooSmall();
if ((bmp.Width <= bmp.Height) && (bmp.Width < 768 || bmp.Height < 1024))
throw new ImageDimensionTooSmall();
fileStream.Position = 0;
}
on client side I try to catch error by the following way:
$('#fileupload').fileupload({
url: '/SmartphonePhotographer/ManageFiles?ResponseID=' + ResponseID,
error: function (e, data) {
alert('error');
}
});
'data' variable always has 'error' value. 'e' has many properties, including statusText='Internal server error' and responseText (html page with exception). Question - how can I pass error message on server side to catch it on client side (maybe, there is an json format for errors, but I did not find it in documentation)
It goes to the error event because you are throwing an exception in your server side code. So the ajax call is getting a 500 internal error response.
What you can do is, instead of throwing an exception, return a json response with the error messages.
[HttpPost]
public ActionResult SaveImage()
{
if(IsFileNotValid()) //your method to validate the file
{
var customErrors = new List<string> {"File format is not good",
"File size is too bib"};
return Json(new { Status = "error", Errors = customErrors });
}
//Save/Process the image
return Json ( new { Status="success", Message="Uploaded successfully" });
}
And in the done() event, you can inspect the json response and show the error messages as needed.
$('#fileupload').fileupload({
url: '/SmartphonePhotographer/ManageFiles?ResponseID=' + ResponseID,
error: function (e, data,txt) {
alert('error' + txt);
}
}).done(function(response){
if(response.Status==="error")
{
$.each(services.Errors, function (a, b) {
alert(b);
});
}
});
With this approach, you can send multiple validation errors back to the client and client can process(show to user ?) it.
MVC 6
In MVC6, you can return an HttpStatusCode response directly from the MVC controller action. So no need to send a JSON response yourself.
[HttpPost]
public IActionResult SaveImage()
{
var customErrors = new List<string> { "File format is not good",
"File size is too bib" };
return HttpBadRequest(customErrors);
}
This will send a 400 Response to the caller with the data we passed(the list of errors) in the response. So you can access the responseJSON property of your error xHr object of the error event to get it
error: function (a, b, c) {
$.each(a.responseJSON, function (a, b) {
alert(b);
});
}
I agree your issue is that you are throwing an exception versus returning a controlled response. Most frameworks look for status codes in the 400x or 500x. So you want to return a friendly json object and a status code in those ranges. If you do that your data object in the error block will be what you returned.
MVC Land:
//get a reference to request and use the below.
return this.Request.CreateResponse(HttpStatusCode.BadRequest, "Your message here");
Web Api 2
Use an IHttpActionResult and return BadRequest("My error message"); If you do that it will set your status code and return the response as the data.

Internal server error 500 in backbone

while saving form details using backbone i m getting error as
POST http://localhost:8080/gamingengine/restful-services/badges 500 (Internal Server Error)
st.ajaxTransport.sendjquery.js:4
st.extend.ajaxjquery.js:4
Backbone.ajaxbackbone.js:1197
Backbone.syncbackbone.js:1178
_.extend.syncbackbone.js:284
_.extend.savebackbone.js:490
Backbone.Form.extend.saveBadgesbadges.js:219
st.event.dispatchjquery.js:3
st.event.add.y.handle
Uncaught SyntaxError: Unexpected token <
st.extend.parseJSONjquery.js:2
window.clearErrorscommon.js:386
st.event.dispatchjquery.js:3
st.event.add.y.handlejquery.js:3
st.event.triggerjquery.js:3
rjquery.js:4
st.ajaxTransport.send.r
my backbone code is as follows
this.model.save(this.getValue(), {
//beforeSend : setHeader, //added
iframe : true,
wait : true,
files : $file,
elem : this,
data : _.omit(this.getValue(), ['iconFile']),
silent : true,
success : function(model, response, options) {
alert("inside save..");
var error = false;
_.each(response, function(val, key) {
if (app.BadgesView.fields[key]
&& val instanceof Object
&& val.error) {
error = true;
app.BadgesView.fields[key]
.setError(val.message);
}
});
if (!error) {
app.BadgesView.model.set(model);
app.BadgesListCollection.add(model);
return;
}
return false;
},
error : function(model, response, options) {
console.log("error while save in badges.js : ");
}
});
and server side code is as follows which is using resteasy
#POST
#Consumes("multipart/form-data")
#Produces("text/html")
#Cache(noStore = true)
public final Response saveBadges(
#MultipartForm final BadgesForm badgesForm) throws IOException {
System.out.println("saveBadges called........");
final int no_of_coins = badgesForm.getNo_of_coins();
final String badge_name = badgesForm.getBadge_name();
final int score = badgesForm.getScore();
final int badge_id = badgesForm.getBadge_id();
final byte[] iconFile = badgesForm.getIconFile();
final Validator validatorNumeric = ValidationFactory
.getTextFieldNumericValidator();
validatorNumeric.validate("no_of_coins", no_of_coins,
threadlocalExceptions.get());
System.out.println("iconFile :" + iconFile);
if (iconFile.length >= GamingConstants.ONE) {
ValidationFactory.getImageContentValidator().validate("iconFile",
iconFile, threadlocalExceptions.get());
ValidationFactory.getImageSizeValidator().validate("iconFile",
iconFile, // added size // validator
threadlocalExceptions.get());
}
if (threadlocalExceptions.get().isEmpty()) {
try {
final Badges badges = new Badges();
badges.setNo_of_coins(no_of_coins);
badges.setBadge_name(badge_name);
badges.setScore(score);
badges.setBadge_id(badge_id);
final Coin coin = new Coin();
coin.setId(badgesForm.getCoin());
badges.setCoin(coin);
Badges.save(badges);
final Badges badgesObj = new Badges();
badgesObj.setBadge_id(badges.getBadge_id());
badgesObj.setCoin(coin);
badgesObj.setBadge_name(badges.getBadge_name());
badgesObj.setNo_of_coins(badges.getNo_of_coins());
badgesObj.setScore(badges.getScore());
if (iconFile.length >= GamingConstants.ONE) {
final String imgPath = "restful-services/badges/"
+ badges.getBadge_id() + "/image";
badgesObj.setIconPath(imgPath);
final String fileName = path + badges.getBadge_id()
+ ".png";
CommonUtils.writeIcon(iconFile, fileName);
} else {
badgesObj.setIconPath(defaultPath);
}
Badges.update(badgesForm.getBadge_id(), badgesObj);
final gamingengine.bind.Badges bindBadges = new gamingengine.bind.Badges();
bindBadges.setBadge_id(badgesObj.getBadge_id());
bindBadges.setCoin(badgesObj.getCoin());
bindBadges.setNo_of_coins(badgesObj.getNo_of_coins());
bindBadges.setBadge_name(badgesObj.getBadge_name());
bindBadges.setIconPath(badgesObj.getIconPath());
bindBadges.setScore(badgesObj.getScore());
final ObjectMapper mapper = new ObjectMapper();
final String jsonString = mapper.writeValueAsString(bindBadges);
return Response.ok().entity(jsonString).build();
} catch (DBException e) {
if (e.getMessage().startsWith(DBException.PARENT_NOT_EXISTS)) {
final String fieldName = e.getMessage()
.substring(e.getMessage().indexOf("-") + 1).trim()
.toLowerCase();
e.getValidationException()
.setMessage(
"The "
+ fieldName
+ " is already deleted.Please refresh the page ");
threadlocalExceptions.get().put(fieldName,
e.getValidationException());
}
}
}
final Map<String, ValidationException> exceptions = threadlocalExceptions.get();
threadlocalExceptions.remove();
final ObjectMapper mapper = new ObjectMapper();
final String exceptionJsonString = mapper
.writeValueAsString(exceptions);
return Response.ok().entity(exceptionJsonString).build();
}
while saving data of the form, backbone does not call the saveBadges() method of server side code
in chrome network it shows as
badges
/gamingengine/restful-services
POST
500
Internal Server Error
text/html
now i tried as
data:this.getvalue() in save() its sending all values to server except for iconPath
**iconPath : {
type : "FilePicker",
title : "Icon"
}**
and in save() of backbone
**var $file = $('input[name="iconPath"]', this.el);** this two lines are not sending iconPath, its empty any guesses
any help appreciated!!! thanks
The issue could be related to the content-type expected by your service, "multipart/form-data". Backbone by default does not provide an implementation to send a multipart request on the "save" method.
Here is a link with information about how you can send the multipart-request:
multipart form save as attributes in backbonejs
Also, message that you are receiving about the unexpected character ">" could be related to the "dataType" associated to the request, try to change it to "text" to avoid parsing to JSON, adding that you should be getting the correct error.
this.model.save(this.getValue(), {
//beforeSend : setHeader, //added
iframe : true,
wait : true,
files : $file,
dataType: "text",
elem : this,
data : _.omit(this.getValue(), ['iconFile']),
silent : true..
}
I will suggest to review your developer console as well in Chrome, Safari or Firefox to see how the request is been sent to the server, that could give you a better understanding how your request is been received by the server.
Also, try testing your service by external "Restful" tool, chrome provided the "Advance Restful Client" where you can test your service.
Hope this information helps to solve your issue or guide you in the right direction.

Categories