I am trying to use the FileReader to obtain the base-64 representation of an image and submit that to a .net WebApi service for image uploading.
My problem is that the contents of fileReader.result are not valid as a base-64 encoded image, at least according to .net.
I am just using a very simple method, and testing with fiddler to post to the service. If I post the complete result string from filereader.result, I get an error "Invalid length for a Base-64 char array or string" when I try and read the string using FromBase64String.
public void Post([FromBody]string imgString)
{
var myString = imgString.Split(new char[]{','});
byte[] bytes = Convert.FromBase64String(myString[1]);
using (MemoryStream ms = new MemoryStream(bytes))
{
Image image = Image.FromStream(ms);
image.Save("myBlargyImage.jpg");
}
}
Is cut+paste into fiddler doing something to the string that I need to account for here, or is there something else I am not doing correctly? This seems like it should be straightforward: Encode the image as a string, send the string, decode the string, save the image.
For example, using filereader to display a preview of the image on the client, I get the following in filereader.result:
src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAgEAyADIAAD/...oBUA00AqYL/AMCg3//Z"
I have tried both sending the entire string ("data...Z"), and just the Base64 string. Currently, I am splitting the string server side to get the Base64 string. Doing this, I always get the invalid length error.
Alternatively, I have tried sending just the base64 string. Not knowing if the leading / was actually part of the string or not, I deleted it in the post body. Doing THIS, I can actually read the value into a byte array, but then I get an error using Image.FromStream that the array is not a valid image.
So, either I get an error that the entire string as provided by filereader is an invalid length, or, I hack it up and get an error that even if it is a valid length, it is not a valid image (when reading the bytearray). That is what makes me wonder if there is some issue of translation or formatting between the filereader.read, dev tools in chrome, then cutting and pasting into fiddler.
UPDATE:
I tried a more realistic implementation by just taking the filereader.result and putting it in a $.post() call, and it works as expected.
It appears I was right, that I, or notepad++, or fiddler, are doing something to the data when I touch it to cut and paste filereader.result into a service call.
If someone knows exactly what that might be, or how one can verify they are sending a valid base-64 encoding of an image to a service, it might help others who are attempting the same thing in the future.
Again, if in the browser filereader.result yielded 'data:image/jpeg;base64,somestring', I was simply copying that string from the developer tools panel, creating a fiddler call and in the request body including the copied string: "=data:image/jpeg;base64,somestring". Somehow, the base-64 'somestring' was getting munched in the cut+paste.
function readURL(input) {
if (input.files && input.files[0]) {
reader = new FileReader();
reader.onload = function (e) {
$('#imgPreview').attr('src', e.target.result);
$.post('/api/testy/t/4',
{'':e.target.result}
);
};
reader.readAsDataURL(input.files[0]);
reader.onloadend = function (e) {
console.log(e.target.result);
};
}
}
$("#imgUpload").change(function () {
readURL(this);
});
Don't forget to remove the 'noise' from a dataUrl,
For example in
data:image/png;base64,B64_DATA_HERE
you have to remove the data:image/png;base64, part before, so you process only the base 64 portion.
With js, it would be
var b64 = dataUrl.split("base64,")[1];
Hope this helps. Cheers
A data uri is not a base64 encode string, it may contain a base64 encoded string at the end of it. In this case it does, so you need to only send the base64 encoded string part.
var imagestr = datauri.split(',')[1];
sendToWebService(imagestr);
Make sure fiddler is not truncating the Base 64 String
Related
I'm using (or attempting to!) the code for encrypting/decrypting a string found in this post Encrypting & Decrypting a String in C#.
If I call the functions directly, i.e.
StringHelper sHelp = new StringHelper();
var encryptMe = sHelp.EncryptString("comahony#centlaw.com", "myPassphrase");
Returns /sx3sL4DE7sM2klGKN3V+CQKdP02ZxbVxANjDh2yfGo= which is perfect
and if I then call
var decryptMe = sHelp.DecryptString(encryptMe, "myPassphrase");
Returns comahony#centlaw.com which again is what I'm after.
But if I pass the encrypted string on parameter on the querystring. i.e.
http://localhost:12345/sso?c=/sx3sL4DE7sM2klGKN3V+CQKdP02ZxbVxANjDh2yfGo=
and call the decryption function using:
var decryptMe = sHelp.DecryptString(Request.QueryString["c"].ToString(), "myPassphrase");
I'm getting the error of "Invalid length for a Base-64 char array or string."
From digging around on the net it appears to be something to do with the parameter needing to be URLEncoded but try as I might I just can't get past this error.
Could something shed some light please?
Thanks,
C
I'm trying to add a JPEG comment to an image file using WPF. Trying the following code throws me an ArgumentOutOfRangeException. Setting other properties works without problems.
using (Stream read = File.OpenRead(#"my.jpeg"))
{
JpegBitmapDecoder decoder = new JpegBitmapDecoder(read, BitmapCreateOptions.None, BitmapCacheOption.None);
var meta = decoder.Frames[0].Metadata.Clone() as BitmapMetadata;
meta.SetQuery("/app1/ifd/exif:{uint=40092}", "xxx"); // works
meta.SetQuery("/com/TextEntry", "xxx"); // does not work
}
To be clear: I have to set the /com/TextEntry field which is listed in MSDN http://msdn.microsoft.com/en-us/library/windows/desktop/ee719904%28v=vs.85%29.aspx#_jpeg_metadata
The data is read by another application which only supports this tag, so it is not an option to use other "comment" fields.
Any ideas?
The data type for /com/TextEntry is a bit tricky, it requires an LPSTR. Which is a raw 8-bit encoded string pointer. You can do this by passing a char[] for the argument. Fix:
meta.SetQuery("/com/TextEntry", "xxx".ToCharArray());
Do note that text encoding might be an issue if you use non-ASCII characters, you'll get text encoded in the machine's default code page (Encoding.Default).
I'm trying to set up a very basic ZeroMQ-based socket link between Python server and C# client using simplejson and Json.NET.
I try to send a dict from Python and read it into an object in C#. Python code:
message = {'MessageType':"None", 'ContentType':"None", 'Content':"OK"}
message_blob = simplejson.dumps(message).encode(encoding = "UTF-8")
alive_socket.send(message_blob)
The message is sent as normal UTF-8 string or, if I use UTF-16, as "'\xff\xfe{\x00"\x00..." etc.
Code in C# is where my problem is:
string reply = client.Receive(Encoding.UTF8);
The UTF-8 message is received as "≻潃瑮湥≴›..." etc.
I tried to use UTF-16 and the message comes through OK, but the first symbols are still the little-endian \xFF \xFE BOM so when I try to feed it to the deserializer,
PythonMessage replyMessage = JsonConvert.DeserializeObject<PythonMessage>(reply);
//PythonMessage is just a very simple class with properties,
//not relevant to the problem
I get an error (obviously occurring at the first symbol, \xFF):
Unexpected character encountered while parsing value: .
Something is obviously wrong in the way I'm using encoding. Can you please show me the right way to do this?
The byte-order-mark is obligatory in UTF-16. You can use UTF-16LE or UTF-16BE to assume a particular byte order and the BOM will not be generated. That is, use:
message_blob = simplejson.dumps(message).encode(encoding = "UTF-16le")
what i need to do is sending a file from java to c#. the java act as the client meanwhile, c# act as server.
the file is loaded in java through fileinputstream and its been converted to utf8 then base64. see the code.
FileInputStream fin=new FileInputStream(fileName);
byte[] content = new byte[fin.available()];
fin.read(content, 0, content.length);
String asString = new String(content, "UTF8");
byte[] newBytes = asString.getBytes("UTF8");
String base64 = Base64.encodeToString(newBytes, Base64.DEFAULT);
and the server (using c# language) will read the data send and convert it back as a file. im using base64 then to utf8 and last i am not sure how to make it. what im trying to send is video.mp4 size of 144kb or less. so far, the output shows the catch of "WRONG FORMAT". see the code.
try
{
for (int i = 0; i <= _server.Q.NoOfItem - 1; i++)
{
words = _server.Q.ElementAtBuffer(i).ToString();
//textBox1.Text = words;
byte[] encodedDataAsBytes = System.Convert.FromBase64String(words);
string returnValue = System.Text.Encoding.UTF8.GetString(encodedDataAsBytes);
textBox1.Text = returnValue;
}
}
catch (ArgumentNullException argNull)
{
textBox1.Text = "Received null value";
}
catch (FormatException FrmtEx)
{
textBox1.Text = "Wrong format";
}
you can ignore the for (int i = 0; i <= _server.Q.NoOfItem - 1; i++) as this is the way i want to capture/retrieve the data sent.
p/s: it works when im just trying to pass any string without load the file (string >> utf8 >> base64) and to receive (base64 >> utf8 >> string).
the file is loaded in java through fileinputstream and its been converted to utf8
Then you've lost data. Video data is not text data, so don't load it as text data. Treat it as binary data - by all means encode it to base64 if you need to represent it as a string somewhere but don't perform any text decoding on it, as that's only meant for encoded text data, which this isn't.
It's really important to understand what's wrong here. The only thing the two lines below can do is lose data. If they don't lose data, they serve no purpose - and if they do lose data, they're clearly a bad idea:
String asString = new String(content, "UTF8");
byte[] newBytes = asString.getBytes("UTF8");
You should analyze how you ended up with this code in the first place... why did you feel the need to convert the byte array to a string and back?
jowierun's answer is also correct - you shouldn't be using available() at all. You might want to use utility methods from Guava, such as Files.toByteArray if you definitely need to read the whole file into memory in one go.
p/s: it works when im just trying to pass any string without load the file (string >> utf8 >> base64) and to receive (base64 >> utf8 >> string).
Well yes - if you start with text data, then that's fine - UTF-8 can represent every valid string, and base64 is lossless, so you're fine. (Admittedly you could break it by presenting an invalid string with half of a surrogate pair, but...) The problem is at the point where you treat non-text data as text in the first place.
You shouldn't use fin.available() to assume you can read the file in one go. That is likely to work for only small files. Instead you need to do the read in a loop and collect all the contents together before you encode it.
It would make sense to (on the java side at least) to have a decode that routine you can use to TEST that your encode is working (a unit test perhaps?). You will probably find that test is failing consistently with the problem you are getting.
I want to output a Byte[] array to a string so I can send it along a HTTPRequest. Can it be done? And will the server pick up the data and create a file from it? Or does some special encoding need to be done?
The file is an image. At the moment I have:
Byte[] fBuff = File.ReadAllBytes("C:/pic.jpeg");
I need to take what's in fBuff and output it to send along a post request.
Use the Convert.ToBase64String method
Byte[] fBuff = File.ReadAllBytes("C:/pic.jpeg");
String base64 = Convert.ToBase64String(fBuff);
This way the string will as compact as posible and is sort of the "standard" way to writing bytes to string and back to bytes.
To convert back to bytes use Convert.FromBase64String:
String base64 = ""; // get the string
Byte[] fBuff = Convert.FromBase64String(base64);
You could just create a String where each byte is a character of the String. If you do the same opposite procedure at the receiver you will not have any problems (I have done something similar but in Java).
Convert.ToBase64String looks like your best option to store the bytes in a transmittable array, you should look into these functions.
If you are sending just the file, you can use the UploadFile method of the WebClient class:
using (WebClient client = new WebClient) {
client.UploadFile("http://site.com/ThePage.aspx", #"C:\pic.jpeg");
}
This will post the file as a regular file upload, just as from a web page with a file input. On the receiving server the file comes in the Request.Files collection.
Any reason of not using the WebClient upload file?