How would I go about debugging what's wrong with a string that I believe is in Base64 format, but which in VB using the below line of code
Dim theImage As Drawing.Image = imageUtils.Base64ToImage(teststring)
throws the following exception?
{"Base64ToImage(): The input is not a valid Base-64 string as it contains a
non-base 64 character, more than two padding characters, or an illegal
character among the padding characters. "}
The test string itself is far too long to paste here; I tried but reached (a lot) over the character limit. I've tried a few online conversion tools and it doesn't seem to work there either. At first I thought I was passing the string wrong from my ajax call to the web method VB code behind...but I've tried hard-coding my string into the function as well with the same failure. So, I'm convinced the string itself is bad data.
It looks like:
Dim teststring = "dataImage/ png;base64,
iVBORw0KGgoAAAANSUhEUgAAB4AAAAQ4CAYAAADo08FDAAAgAElEQVR4Xuy9268sWbbe9UVE3i /
rvte + V....K/1Tx5/8A736wVclDQN4AAAAASUVORK5CYII="
But I also tried removing the "dataImage" part and using
Dim teststring =
"iVBORw0KGgoAAAANSUhEUgAAB4AAAAQ4CAYAAADo08FDAAAgAElEQVR4Xuy9268sWbbe9UVE3i /
rvte + V....K/1Tx5/8A736wVclDQN4AAAAASUVORK5CYII="
And it doesn't make a difference.
I am getting this string in javascript using this function:
btnFreeze.onclick = video.onclick = function (e) {
e.preventDefault();
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
canvas.getContext('2d').drawImage(video, 0, 0);
alert("got here");
$hfLicenseScreenshot.val(canvas.toDataURL());
$img.css("background-image", "url(" + $hfLicenseScreenshot.val() + ")");
$("#hiddenTextbox").val($hfLicenseScreenshot.val());
//$("#save").show();
return false;
};
...where ultimately the string is from
canvas.toDataURL()
and about halfway through that function there is a hidden field called $hfLicenseScreenshot, from which I am saving the value into a "hidden" textbox (I dont know why my variable was getting lost, I know it's redundant but that's why I saved the value to a textbox called hiddentextbox. I get the sstring from hiddentextbox later, like:
$("#hiddenTextbox").val().toString();
So, I have no idea how to go about debugging this image base 64 string. I've tried different images taken from my webcam and it's just not working with any of them. Any ideas?
...I don't know if it's been serialized or not, since I think the JSON stringify method is supposed to do that. I might be confused there.
...Here is my ajax call:
$.ajax({
type: "POST",
url: "/BackCode/FirstPage.aspx/SaveData",
data: JSON.stringify({ currentData: currentData, str: makeblob(str) }),
contentType: "application/json; charset=utf-8",
dataType: "json",
async: true,
currentData: currentData,
success: function (resp) {
resp = resp.d;
if (resp.success) {
if (typeof callback === "function")
callback.apply(this, [resp]);
load();
} else {
$.statusMessage(resp.statusMessage, "red");
}
},
error: function (jsonObject, textStatus, errorThrown) {
$.statusMessage(errorThrown, "red");
}
});
I have also been having issues with this, and it goes into the last error function a lot:
$.statusMessage(errorThrown, "red");
So I don't know whether I'm passing it correctly either.
The following works for me:
Dim base64String = "Qk2uAAAAAAAAADYAAAAoAAAABgAAAAYAAAABABgAAAAAAAAAAADEDgAAxA4AAAAAAAAAAAAA////AAAAAAAAAAAAAAAA////AAAAAAD///////////////8AAAAAAP///////////////////////wAA////////////////////////AAD///8AAAD///////8AAAD///8AAP///////////////////////wAA"
Dim base64Bytes = Convert.FromBase64String(base64String)
Using memoryStream = New MemoryStream(base64Bytes)
Dim image As Image = Image.FromStream(memoryStream)
image.Save($"C:\Users\{Environment.UserName}\Desktop\Smile.bmp")
End Using
I've removed the initial metadata which indicates what type of image it is, the original string was:
data:image/bmp;base64,Qk2uAAAAAAAAADYAAAAoAAAABgAAAAYAAAABABgAAAAAAAAAAADEDgAAxA4AAAAAAAAAAAAA////AAAAAAAAAAAAAAAA////AAAAAAD///////////////8AAAAAAP///////////////////////wAA////////////////////////AAD///8AAAD///////8AAAD///8AAP///////////////////////wAA
Try removing the spaces from your base64 encoding - as they're not a valid base64 character - and the metadata from the start.
Here are the valid base64 characters taken from Wikipedia:
I tried removing whitespace like some other suggestions here, and that did not fix my problem (although I'm sure that was likely a secondary problem).
In my case, my string wasn't actually a valid image at all because I had tried to pass it from Ajax to the VB WebMethod as an object (this was because passing as a string was not working). And at one point I had tried converting it to a Blob object....so my test string was just something totally invalid. I should have just left it as a string in both front end and backend. So, I don't even know what my string one that I posted earlier, but it wasn't an image.
Eventually I realized that my string on the front-end was too long, which was my actual/original issue. Now I realize the irony of having mentioned earlier that the string was too long to post in my question. There is something in the WebConfig you can set for maxlength of an image string:
<webServices>
<jsonSerialization maxJsonLength="86753010">
</jsonSerialization>
</webServices>
So, the json serialization was failing because I had this code commented-out. I commented it back in and made the number bigger, and that fixed my issue. So then I was able to pass the string properly and everything worked!
Related
I have this piece of code that encodes an array of results from a database search:
foreach($searchResults[$i] as $key => $value) {
$searchResults[$i][$key] = rawurlencode($value);
}
I had to encode in order to pass the data as JSON to another page. On the other page, I'm trying to decode the resulting object like this in Javascript:
if (results !== null) {
for (var i = 0; i < results.length; i++) {
$.each(results[i], function (key, value) {
results[i][key] = decodeURIComponent(results[i][key]);
});
}
}
My problem is that I'm getting a URIError due to malformed URI. There are several pieces of data being passed, so my real question is if there is some method or tool that allows you to search an array of strings for the offending item. I have several results and don't relish the idea of having to go through them character by character to find the offending encoding. Does anyone have any suggestions? If I could figure out what character/characters is causing this error I would be on my way to figuring out a solution. I'm a coding newbie, so please forgive any incorrect use of terminology.
BTW - Sometimes this code works perfectly... I'm trying to find a way to narrow down the offending database items that are causing this error to occur periodically.
Using node.js (0.10.35), and attempting a post
A console.log(formData); shows me a problem, but I can't see why it's happening
Here's a subset of what the console.log shows ...
{ 'ctl00$mainRadScriptManger': 'stuff',
mainRadScriptManger_TSM: 'more stuff' }
I'm not sure where the quotes around ctl00$mainRadScriptManger come from, and also why mainRadScriptManger_TSM doesn't have quotes.
var formData = {
ctl00$mainRadScriptManger: 'stuff', mainRadScriptManger_TSM: 'more stuff
}
It is not an ERROR, nor it is getting printed randomly.
Its because your property name(key) contains '$'.
Putting space in your property name(key) also causes key to be printed in quotes.
I'm trying to figure out how to parse a form entry to set the model attribute to something else; e.g., extracting the video ID of a youtube video from a URL input. Is there a way to use parsers/formatters (6.21 features?) to accomplish this easily? I hoped to find a good example for this, and maybe there is one somewhere, but perhaps this would make a good one if there's not.
Here is a working example of what I'm attempting to accomplish, but in multiple steps and without the use of parsers. Any help adapting the code to set model.videoID from a URL in a single step (or fewer than 3 steps, at least) would be very appreciated. Thank you for your help with this and my other past questions. :)
Wow, this was much easier than I expected to implement. Here is the modification of the JS Bin which uses parsers, recently added with angular-formly#6.21.0, to extract the video ID from a YouTube URL in one function. It also, conveniently, validates itself!
Here is the relevant code, to summarize:
{
key: 'vidid',
type: 'input',
parsers: [extractID],
templateOptions: {
label: 'YouTube Video',
placeholder: 'Insert video URL here'
},
...
function extractID(value) {
if (value != undefined || value != '') {
var regExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=|\?v=)([^#\&\?]*).*/;
var match = value.match(regExp);
if (match && match[2].length == 11) {
return match[2];
}
}
};
I have this link
#Ajax.RouteLink("Bid", RouteNames.Ajax.BidOnLot,
new
{
lotId = Model.Lot.Id,
bidAmount = Model.NextBidAmountForUser
},
new AjaxOptions
{
HttpMethod = "POST",
OnFailure = "OnFailure",
OnSuccess = "OnSuccess"
})
and this action method
[AjaxOnly, HttpPost]
[Route("ajax/bid-on-lot/{lotId}/{bidAmount}", Name = RouteNames.Ajax.BidOnLot)]
[Authorize]
public JsonResult Bid(string lotId, decimal bidAmount)
RouteNames.Ajax.BidOnLot is set to "BidOnLot"
But for some reason when I click on the link, I get a 404 with this message.
404 Not Found - http://localhost:12472/ajax/bid-on-lot/lot-901/210.0
When I have only the LotId parameter everything works normally but adding an additional parameter makes it all fail.
Why is this happening?
Just in case anyone else struggles with this in the future let me tell you what the issue was. Passing a decimal parameter was the issue. Passing an int, double or string is fine but when I made it a decimal it failed.
How do you deal with the fact, that URLs are case sensitive in xPages even for parameters? For example URL:
my_page.xsp?folderid=785478 ... is not the same as ...
my_page.xsp?FOLDERID=785478
How to make, for example, a proper check that params contain some key e.g.
param.containsKey("folderid") which desnt work when there is 'FOLDERID' in URL.
I'd suggest defining a couple convenience #Functions:
var #HasParam = function(parameter) {
var result:boolean = false;
for (var eachParam : param.keySet()) {
if (eachParam.toLowerCase() == parameter.toLowerCase()) {
result = true;
break;
}
}
return result;
};
var #GetParam = function(parameter) {
var result = "";
if (#HasParam(parameter)) {
for (var eachParam : param.keySet()) {
if (eachParam.toLowerCase() == parameter.toLowerCase()) {
result = param.get(eachParam);
break;
}
}
}
return result;
};
Then you can safely query the parameters without caring about case. For bonus points, you could add requestScope caching so that you can skip looping through the keySet if you're examining a parameter that you've previously looked at during the same request.
you may use this function:
context.getUrlParameter('param_name')
then test if it's null or not.
make sure to decide for one,so either upper or lowercase
other than that i'd suggest something like
KeyValuePair<string,string> kvp = null;
foreach(KeyValuePair<string,string> p in param)
{
if(UPPERCASE(p.Key) == UPPERCASE("folderid"))
{
kvp = p;
break;
}
}
syntax isn't correct and idk the uppercase method in c# right now,but you get the point
The easiest answer is ofcourse the obvious. Be sure that the parameters you are using througout your application are always the same on every url you are generating and know what to expect. A good approach to accomplish this is to create a ssjs function which generates url's for you according to the objects you submit.
In this function you could check which object you are receiving and with the use of keywords and so forth generate the correct url. This way generating twice a url with the same input parameters should always generate the exact same url.
another option would be just to double check with a bit of code like this
var key = "yourkey";
if(param.contains(#uppercase(key)) || param.contains(#lowercase(key)){
// do stuff
}
But should not be necesarry if the url you are parsing is generated by your own application
Edit after post of topic starter
Another option would be to grap the url directly from from the facescontext and to convert it to a string first. When it is a string you can parse the parameters yourself.
You can combine server side substitution/redirection to get around the issue that David mentioned. So a substitution rule will redirect incoming patern like this:
http://myhost/mypage/param (/mypage/* => which converts to - /dbpath/mypage.xsp?*) - substitution is tricky so please handle with care.
Also I believe I read somewhere that context.getUrlParameter is not case sensitive - can someone please confirm this.
Hope this helps.