I have a android mobile application that has functionality to set a profile picture.
I send a variable containing the path of the image to a method that does the following:
string imagePath = _ProfilePicture.GetTag (Resource.String.profile_picture_path).ToString ();
byte[] imageBytes = System.IO.File.ReadAllBytes(imagePath);
Stream imageStream = new MemoryStream(imageBytes);
After this block of code I send the imageStream variable to UploadUserProfilePicture(imageStream); which is located on the WCF Service
Currently it only sends the stream, but because we cannot send another parameter containing the extension. We save all images as png. I have however found a library that requires the stream to be parsed to bytes and then based on the bytes the file type can retrieved.
However when I then try to use the same stream to Write the file to the location on the server, the position is at the end so the file created is always 0 bytes.
I have tried:
Doing the conversion to Bytes in another method and only returning the fileType, however the originals position was still at the end.
The CopyTo function gave me the same results.
I tried using the Seek function and setting it's position back to zero however the I get a NotSupportedException.
I tried this as well:
string content;
var reader = new StreamReader(image);
content = reader.ReadToEnd();
image.Dispose();
image = new MemoryStream(Encoding.UTF8.GetBytes(content));
^ this seems to corrupt the stream as I cannot get the FileType nor write it to the above location.
I have also had a look at: How to read a Stream and reset its position to zero even if stream.CanSeek == false
This is the method on the WCF Service:
public Result UploadUserProfilePicture(Stream image)
{
try
{
FileType fileType = CommonMethods.ReadToEnd(image).GetFileType();
Guid guid = Guid.NewGuid();
string imageName = guid.ToString() + "." + fileType.Extension;
var buf = new byte[1024];
var path = Path.Combine(#"C:\" + imageName);
int len = 0;
using (var fs = File.Create(path))
{
while ((len = image.Read(buf, 0, buf.Length)) > 0)
{
fs.Write(buf, 0, len);
}
}
return new Result
{
Success = true,
Message = imageName
};
}
catch(Exception ex)
{
return new Result
{
Success = false,
Message = ex.ToString()
};
}
Link to Library Used: https://github.com/Muraad/Mime-Detective
The CommonMethods.ReadToEnd(image) method can be found here: How to convert an Stream into a byte[] in C#? as the questions answer
I hope this is enough information on my problem.
On the server side, you receive a stream from WCF that does not support seek operations. You can, however, read the stream to memory as the GetFileType method requires an array of bytes as input parameter. Instead of accessing the original stream again, you can write the bytes of the array to disk in a very easy way using the File.WriteAllBytes method:
public Result UploadUserProfilePicture(Stream image)
{
try
{
// Store bytes in a variable
var bytes = CommonMethods.ReadToEnd(image);
FileType fileType = bytes.GetFileType();
Guid guid = Guid.NewGuid();
string imageName = guid.ToString() + "." + fileType.Extension;
var path = Path.Combine(#"C:\" + imageName);
File.WriteAllBytes(path, bytes);
return new Result
{
Success = true,
Message = imageName
};
}
catch(Exception ex)
{
return new Result
{
Success = false,
Message = ex.ToString()
};
}
}
Please note that this means that you store a possibly large amount of bytes in memory, in the same way you already did before. It would be better if you could use the stream without reading all bytes into memory, so looking for an alternative for the GetFileType method that can handle a stream is well worth the time. You could then first save the image to a temporary file and then open a new FileStream to discover the correct file type so that you can rename the file.
Related
I have a very strange issue. I am converting Image to base64string in an asp.net web API hosted in Azure app service and getting the wrong image string.
If I run the code in the local machine I am getting the correct value.
public static string GetImageFromSharePointOnline(string imageUrl)
{
try
{
using (var clientContext = CreateContext(URL))
{
clientContext.ExecutingWebRequest += ExecutingWebRequest;
FileInformation fileInformation = null;
Stream returnStream = new MemoryStream();
int readCount;
var buffer = new byte[8192];
Uri image = new Uri(imageUrl);
try
{
fileInformation = Microsoft.SharePoint.Client.File.OpenBinaryDirect(clientContext, image.AbsolutePath);
while ((readCount = fileInformation.Stream.Read(buffer, 0, buffer.Length)) != 0)
{
returnStream.Write(buffer, 0, readCount);
}
}
catch (Exception ex) { }
returnStream.Seek(0, SeekOrigin.Begin);
return "data:image/" + GetFileExtensionFromUrl(imageUrl) + ";base64," + Convert.ToBase64String(buffer);
// return Convert.ToBase64String(buffer);
}
}
catch (Exception ex) { }
}
Azure web api output:
data:image/jpg;base64,VHdEqK7rHUHQQ0VMQUMN/T0MMGKzMFUEsTYAdpNTJgXxeGxYh+qoll/MSfCD7AOvxrk3738OrTjPyJZGHi5kcUcsCBYkCJtAUgdeq27da89em0/L0vPW/gt8zw0mAwkS74zmwY9Qe411c+31+rm6cvlx47jzly7b7I1F5Htew9g7Seyt79PmZZ05/VwYcPjsGFlKY6NtIJMgDk2N9d37AK49u21/Lq15axZy+Jw893kmiAlc38xPC1/h1+NTXrtqu3LWlfkeKmwcnypPEp1jfsYV26dJtMuTfn81Pi8ZHzYw6hl8R2sLjRSelTrtjW4OeudjNiQwwlimPDudStzGh0PXs7tK4r02v5dk0k/ClzeBiR8a8iQojqy2ZVCnU27K9eXTa7ea8uvOTXwXY495AAuToAK68ubA/h8Xjwgb0WWX8zMAyj2AHT41x9O1vr06tOMnsWjF4DAUUoWDG4vewsBbpavH6r1xFHkvTsE0LS4sYjnUX2Lor+y3QHutXtz7WXFeXTjLMwtCMEV2uREx0EGSiObJVHJloLES1BajSoqwkQorssNTK4SEIpkws4MC+fv/AOGCw9/QH4E3ry67ftenKfuEooq4nWtxRjs7NKDXKYS5HF5MTC942K+xlF1+8VdLim0zAH0/D/04PbWSQ3PeFAA+y5r17Xy8uU8DUUVhuPQak14vVbgjDKrDVWAIPeDrSrA71Xio3GpKR4opBY+xtCPwr14Xy8u0zATh4wcuM+xv6TXR0v7a8Oc/dDLFDpf7q4nYq+o4h/k7gGxLJcnQC7jtrfK/uY6TwWuGVGzI97W2ncBYm5AuOntrp3viufWeTNFFXG6lmEx+cYf8QKHI9hJH7KC/FFUaIeaqLyOWiiyrNIqj2BiK+jpfEcG881wcAVthXdgKqOLOKDkzVUWoqguRWqNCGJiTTgmJd1iAR76xtvJ7b10t9DnGenJMrjp8pyVNj9OO8qdW92lq8enbF8PbTjmZoFKTFIY3G1lNiDXrLl42YWYj5UkxjkjkWJQWa9gwJA8N7XNzWNsWeW9fF8LcGZPIVCRAljtWwNiR8a87y1/y9J0v+BnHg2IFJBYks9um4/2Wrw2uXtrMNctKuNxOXM2m2JgP5mG1R8WIqa+1voC9Oxf9Kiv+8/7K9OvtjT0YJz52OkaIFKqeliTe47K857bvpPAitiwXGgjQfEKKb+6a+op+qR5fDlrA2ddGFxrcVrn7Z6eixx66qwB8JBJHfeurLmwb0jv4u863661x11wP9VJbgpj/ABJ/UK1z/kzv6KPG+akqzIL+Wyn430FdX+nOcsQxTIHjN17e8ew1yba2OnW5XcfGVMn6lf8AelBHrqNoJPT41nKuXNc1h8RiNPOwMzA+RDe7O342Haa1prmptth55j5DSs0jm7uSzHvJ1Nd2ri2NmJ6RkyOAlzZCVyXAfGToNg7W/mry3742x+HrpwzrkkZMjxyNG4KupIZT1BFdMrnsVzP7aqNebeqghEaguRNUU4+jTkTiSHZuhjKnewG1QSSR3ljXJ/Yk9uv+vb6OMERjTYTcdlcjqJHqziCrSSwC8sWrKB8ydfiQK6OPTHivDrzz5ijwvDS5XFySsCHnW8Z18KjVSfeRf3Vrp1xt+jPPnnVd4rHOLHskN8j8/wDDfqo/b31jp0+m9NMDcOwJuYhVUXLHQACvJ6FPnuUl5mVsTj1L4OL+pPKOjkaX/lFe2muPbz2uRnhcXy+PiUjTc37Kz09nP0JGL9J9Pyn8KxPbdWMCIfS4+n+En9Ipt7pr6UPV8duEf2yJ+NXn7Tf0VsUR+YfLBEdzs3W3Wvpe3bXTHPTrDDePd3W++uS+3TPSvzPH/XcccVm8rzXQF9NLG99St+lXW4uTaZhay+AfB5eLDhlc4+SUcBQ2hBtr2fvbete2vTxl5baeTLBjxIoSNdqL8idwrxty9ZMOkM8Zzjh2PmLEJSdLWLFbe/SpjxlXfkuIw+Tw2xMqMMjA7XsNyN2Mp7CKa7WXJZkhenfTjnmZcfKU+RhyFJL9JGU2sP4SRf3V1b9cTw59OWb5epRANEUI8JFvhauN1PM/W3piR5Xy8YqskVxkhjtBVej3Pbaurh1x4rm7cs+Y87GTr1rtcjsk1+2qgzG1EEMGCbInSKMavrfsAHUmvPbeSZb11tr0/j2wOJ4qCJOrKGKj5mY9WNfO33u1zX0dNZrMLT8viBolQ72kFwB2aaA+0nSsNBPM50JzIgy7bja1+u65IB+FUTxZIsedR4fMZT5ak26aXA/vUQLz5I05EooswA39xJFxVg7z8NFysKxT5E8cP5o4mVVb+a6sT9tWbYZuuUR6O4rBxJ5opJiYkZyGZCPCN1jZR3VudLazdPDvxciTYyhPyEi3vsadfacvQksIZSp6HQ15PRZghVEVF+VQFX3AWpasgb6ugll4YxRIXkaRSFHcoLH8K1zvlneeCXiMAEBQq2t2Pb8K6Y56fYAuxT/CDeuWumBvrO6enZnUkENGQRoQd4rXP2zv6J3prPyG5iFZpndZXYuGYkF2VgGN+27V776+HlrfJ/ijFhYdPurle7omMnmmQIBLYXc92vdrRV6NReoFmTMxsflMplsSZD4V6kg2NVR+DksdpoYIyG3i5bu0uB76gocqIpMhw20q4CsDax0I2m+nZVK8t9dg+n+awZ+PgSGMYohRiqMhILq11YG7bSPEa7eF+pZXJ2nzZYT4J711OYywksyqOpNh8aVmGrgR5ceSxAUowUE26AAWr5O21tfU11kgzHP5g6/GstLMKkksvzqLrYjQ9n4VUBuXznnBd9JC/iHcQLW+FFFpuXSKfPBxwz8bHEyuSLt51iRqpK9lBR5KbdzLMBbckbW96A1QwcbIAgDDoNRUFnmZ0HBciV6jFmI+EZq6+0vokemeaeGZS43RsArqPZ2++ujbXMeE2xT/AIzxSjcjBh3do9hFc9lj2llZk52JhxmSd1iRb+Jjb7KkmVtwryTfWxpLG36LqHiNuoYXBsbU9AHzmE3nwmJVeWVTGsZVjYA7i4K9Otte+vTnth5765GMN3Corgq1hodKxXpFP1sB/wBsZFv3o/6xWuX8mOnp5vhO8cySIdroQyt3EG4rsw5bXpfC81hZ0aozLFk2s0TG1z3rfrXL05XX9HTp0l/UcCALrp7a8XoBZ3OZWFh5OSsZZpH2xfuobWDN/t1qqXuIjRnvK+3dclyL6mgKQ5AjdWU6qQR7xUQXTaoUsVG82BY2JJopU/1MgxZ+PxsKeMXyC7RzfmjZNuo/9Vb02utzGdtfqYeNmOfFyXx5haSM2PcR2Eew19PTaWZj522tlw9L9PcSVxn5KdTop+nXp731+7+yub+z1/5j3/r8v+qLcAqPHlqSApBuWFwPD1IFcTsa42cyY02SDuhhkKd2iquutupv1qgrDykK+TcX81tq+JOu8J2nXVuz8aC5gxQDInnZlklkci4A8Kjounb30Gcjz+LgzmNo0cBVeVmdUIBYL0I10NAv85xmVyHqqRInMcUPlMz3sBZVJGnU+ygYiksLr9PFu8xg8jA9u9F7j+Un7KBe9XemZ48IZHGFrCSSTKjMjFmEgGi3OoFidv2V6c9vPl57zwDcGd7IqDc56Ada6XNTXgPJNIgj8O07iQbWH41N8SeTSW3wJ5fGY2bjtiSiyyAtuHzBrjxA1yTazy67rlyPGSRrhRsuNIcfFMLySSSI27yinhVRbax6k62q/RgG9RpyeHjcOcDHD5MJmbZih8hFtbUbgSRr2jrW9MXOWN8+MF087nvM7zTOs+iyC5Q3UbdQLa6a+2ujXWPDbauOVyWVPGY5MiR4z1RnYjT2E1r5jP1XGBlBvW5GLTNwfAnNUZOX4MNdQuoL2/Ba8uvXHie3py5Z830NL6Zw4ExmgZi4l3rMzO3gILfISY720B2/fXLt0tdOvOQSy8H6niJ41cRnVtzKGXw663B+0dK83oAcPEm8B7P/AAdQffVF3nMH6TBWeCMlTJulPUoGUC1+69BR9VupyeHTdc+Zdk9jMgBP31AL/wBS8zcOHbtbz93vHlVYE3lOJPIYgnhW+XCNAOrL1K/+FdHDp83F9PDtz+pme3pmRFizYvk+XMqbTbZGwttOlgPwrnr2nhT+mhwIMv6aN23FdJQCouupNyd2vs9lRW/TUCDjslXJA8xmLDU/Kv20HWGQeZYsCoPh946dfdVVWhgmbkzhR5AJklfI0JW35tjW3Ht+NBV5nBz88fU4sXnPMnkODYKtnUq+pH7pojvJlIfXe03DNGL37f0+ygN8bHI0Gd4XRnispZJ113zdLsSev5Nf/bQL3qvjOVz+BiwsSJ5so8pGACJQNoxipcGVn8AP5gdvxvW+e0lY3mYyH0f9HhyzR8gmVLiQs2VDCAzCZT8lgb20Ya63H2e06+fTy25eHT03yIn5HHTdcEPYf3GNenaftry5fyhow4slhLuZvNEQCm6gg9etttcd9uyem5M7kxkKmPBFJDsfzGkkKMHCnYoUK1wWsCb6VMQrSzM0K53IqkEuNHJ5ojdnjVTYtqQu7RB2Vf8AUA3E9NelOYEmdHjvvaRllXe6EOOt1BsL9a3/AOm08MfGtRg4P0llZEuBDCd+MCCdzjcA5DWa922vp/5VfvaeU+Nb4JfqDEbhuZfHAvCbSY5bUFCehv1sdK6ue31HN01+a9B4XMhm4jHmyygR40L7gAlzawt069K4t5jauvS51gl9TinFiOIUaAr+l5dtm0D8ttLCstOmDkbYvFpc3+BoAePhzw8g36YVC52bSNvW+lvZRVj1BG2RxjY8khZi4kREsW2rcgdFt99Av8xPLkcphhg6xxMgRXFhfcLkD4VBR/1AwMrKxcGaAB/pPNaSPcN+x9l2C9oBXW3SrAO4rAz0srwMrBlQgj8zi6j7Kocg1RFbk2Jxwt7KTqO0kfsFSrFj0uB5cg6/qHT+6KAfnRbc1ooA0OxyWje+lwdAVOoudPZWlXMGHAi5YZFn+qZdxNztsw2j2flNEGceBFR1Gu61j7u+oha5BxFz5efHSOYAeVJYFihG2+4a62qxR7i8jHyNwjcmRACw3PYbr20Jt2GpUdcudcadQSQJF1uTbTuFIrfH/wCWiOKXDjj2xqY4njtYLpcAj+UfZVZeecck/F/6h4HG5eX9Zk5UbzyFIvK1aOTTaDb8tzXRds6V4TXG8elQZCLM9tQRa/Ya5nQTeW9XR8VysuIkKsE2n9WeKEjcJDazm9v09D239hrc1yl2MHE8scrBiyYowDIAdoYMouAdGW4br2VmrEcn1pxuKuMzJNKuUrNG0SFgAjIp3X2kayfjVmqWsm9Y4A5c8UI5vP8A+Ls/S+Tf89+7T30+fGU+vLyvkpfV3M8vOpxcrIhinlTHdo2CKpewAcgC2g7a69NtdY5t5tae4oObw+KxsVoSkkfli5fZcKRe203rl2ubl06zEwJ8Q3INiY2PlMA/yyESOzWJ7HOt7VlpZ5+XLiCw40qxhlUgm+4FX1N/4l01pBShPKlgTPcMxKg31DfKKIvxQSspO68ttHbUX7O7SooC2BmHIfKyG2rDOka79C53geEHstrUUW5TG87ipds5xZVU+XkAE7SdNQt9KsQtxZXPrKdsm9PNjIs4HgCgP81uprQNiZe+mEUeSyIrhQbuPmPd3LWK1BH0m26KQ/8AyH+kUE+eizI81TMA0Lf7mbaASP3GI67a1BrDTB+qSWRUOWFulyN21CdQO4F/vrTNo3isGV2NgoIF/wDb31mrCzzvO4uNzr4XJ8b5yRhXwslW2kq4G4EdoDbh+ykii3p7JTJ3mDHEEI1bxM+vYLmpUcPU2Kz5UU8I3NEv/MIDYhCfC9u0XuKsUU4bGhfDRyL3Gi3KgW07KWoGPjYeTysXIxYsceW0flNOoUuYxrsLW3bb61cpgVyWhxcKXIl+SNST2f2Vlp51yUWLyPJx+ZFFlvNtWPzUV2W9wAGYHw+M295reWa9C4viYMHDjxYhaOMWUWAA9wGgHsrFqgXN+keMkz8fIkR5QWk2IZGCiSZ1kboV6soIv091amyWCWHx+/KZFRYXIvM4UBiBoOnWlqSM5Py8XJGOgIsoO8m5a/4VItWM6BW9PM5ILxL5qOT01udfdpT8qq4PGzRSxHMdFRlVtoa5JboulEd/UeZhYMUM0+KuQ7kqlzttYduhuKRQbH5WXJl8xwuugRVAUAdBYVcJkcaDKm46URMEyJY28pum0sPDWasIGNyudmZ2MuXK0jRSKgDdniF/jUV6DhqrxlWAZWFiCLgg+yiFFzGmVIkWkYbwgNuFvfYfeK9ErqMPII+cKe4tf8AamYYSfizJrJICQNqgXIt36ipmL5Tgw8/GgkjxMgQuzMQ1tLFFUd+t1vU8Djn8Zn8n5TckuPJIu/zGhZ0El4vLBkUqFLWJFx2VqWDqmLkQT/UDH3sIkiDqYydu69v3/aeyrmM4oziJl5eBmY7RNEOsLtaxYAG1utr1LVhZ9UZsU3F8Fk5EbNPNjPIXb5gLRmxNuutNVo16T5JVx8kbAIIQJJH0uDYWHxptElVvVfLxpzOPFEGXIxlJdwRazgNtIprFtNXAy+dhRy7BGHuQo9/X7azSA6cqRmHDixEx/JyRHMGYs1n3eLcbE3IFvfVsMi+fkSY/HzzxKHeJC+xuhCi5H2VlS7heoxkMjR40UKrfaqjpu66i3Wt/LN2NOOztCjOLOQCwFYrUVeSzTi2d1VoiPDf5vMvoB8LmrIlqXFwx7jOof9QC24i1jroBVqQN5wcWvJSS5OcxlVUVcNR4hpfQnQAjWrCjEYnfiyII1jmMR8qKQbl6eFW6de2sqV/TJlzuanfNJXJjLSSRkW8YYC1v4a1fSflY9Xb+V4NMvjx5sWK7PkLoGVVXU29lJ4oXvT7ifIihB1kYL8O2tVF+b1C3/eeDGsjLgIWx7WsrFwVBN+vj2/AVjDUKuOrp6ieMXKpmEEnuEtr1MLl6ZxeTDKAUJIte+1raaHqOtRFDn+HmnyVnwMYbpNZHWQLfTq0bKtj7mrUqWKi1lXQUVMUExQTWgmpINx1oIz48GTAMfIQSwg3WNhcA+zuqwaxMDDxYnihj2xO6yFNzEb0NwdSe6mUwG8n6YGZmy5kWS0bSsWMbDcAT1s1xp8Ks2Sxei/z7jsLBTDZMpoJGbJiZtm+O3hRWYG1MwC5eN5eD1DLKokycHIkjkknkKu2hDbdCGsp8PyjTsq58A6eS5MLnJ9J5nlRhsVQGtJcG4YkBfhes4Uj8YnKh1X6SVC7WUFGVbnsu37TXplg1eoeRzMX/ACeREaRhkL5sKX8RsBb79KxGqp+sHzI+ThlEjywTL+nELkIy2DWA7+tXVNkMzls6VOPwuKbJjyRIqtksrJGA5t41AN1X29lUa9ZLy2R6hT6fj5mjjhVPqEXesmpO66bgvW1ib01pRrHj5+PDgxRIVf6TJ3sT4RM9hAhbr4fZWcxYEekfT/PYXJRZOWBjxpcuNwdmBFitlJH31btCSr/EemcrD5ts+TItjDeBjxk+NWNgslxYi3WpdiRY470ri4fISZwkuzFjHCi7I03/ALoux0vprS7Lh2g9L8LDMk/kb5o2DJI7MSGU3Btfb91T6pgQTFxUlaVIUWVyS8gUBiT2kgXqK7VBlAqrVR0FFTFBMUE1oJigkKCYoJigkKCQoiQoqQoJCglQboJUG6DKDYoMoMoMFBuoMoFVaqOgoqYoJigmtBMUEhQTFBMUEhQSFESFFSFBIUEqDdBKg3QZQbFBlBlBgoN1BlAqrVR0FFTFBMUE1oJigkKCYoJigkKCQoiQoqQoJCglQboJUG6DKDYoMoMoMFBuoMoP/9kAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
output from my local machine:
data:image/jpg;base64,/9j/4AAQSkZJRgABAgAAZABkAAD/7AARRHVja3kAAQAEAAAAPAAA/+EEJWh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8APD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDAgNzkuMTYwNDUxLCAyMDE3LzA1LzA2LTAxOjA4OjIxICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InV1aWQ6NUQyMDg5MjQ5M0JGREIxMTkxNEE4NTkwRDMxNTA4QzgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OEVDOEIyODRENDcxMTFFN0IwODdFNDUxRTNDRTEzQ0IiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OEVDOEIyODNENDcxMTFFN0IwODdFNDUxRTNDRTEzQ0IiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgSWxsdXN0cmF0b3IgQ1M2IChXaW5kb3dzKSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkQ3QjM5QkJCOTFBOUU3MTFBNEE0RDlCRjU4RjAwQ0FGIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjdCNzYyMDk4ODdBOUU3MTFBQ0MwRDE2NUU0NzdENzFFIi8+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
Can anyone help me with this please.
You're initializing a MemoryStream:
Stream returnStream = new MemoryStream();
(should be var returnStream = new MemoryStream();)
as the container for the bytes read from a Stream.
The Image bytes are read from the source Stream using a buffer:
var buffer = new byte[8192];
which is ok for a NetworkStream.
Assuming Uri image = new Uri(imageUrl); represents the same object in both environments, you the read a [buffer] number of bytes (which is the maximum value, the actual bytes read may be less than that) and write the bytes read - the value is stored in the readCount variable - to the MemoryStream:
try
{
fileInformation = Microsoft.SharePoint.Client.File.OpenBinaryDirect(clientContext, image.AbsolutePath);
while ((readCount = fileInformation.Stream.Read(buffer, 0, buffer.Length)) != 0)
{
returnStream.Write(buffer, 0, readCount);
}
}
When the source Stream is read to end, the MemoryStream contains the Image bytes.
At this point, you want to convert the Image bytes to a Base64String.
Of course, you need to convert the content of your MemoryStream, returnStream, not the buffer content, which is only used as a temporary container for the bytes coming from the source Stream. So just change:
Convert.ToBase64String(buffer);
to:
Convert.ToBase64String(returnStream.ToArray());
Setting returnStream.Position = 0 before calling returnStream.ToArray() is not necessary in this context, but it doesn't hurt either.
Side note: those empty catch blocks don't serve you well. Either add logging features or remove.
I would like to create new blob on FileShareClient in Azure FileShare resource with .NET api. I cannot specify it's size in the beginning (because it will be filled with data later eg. csv file filled with lines, up to couple of GBs).
I was trying to use something like this in my code:
using Azure.Storage.Files.Shares
ShareFileClient fileShare = new ShareFileClient(
"MYConnectionString",
"FileShareName",
"TestDirectoryName");
if (!fileShare.Exists())
{
fileShare.Create(0);
}
var stream = fileShare.OpenWrite(true, 0);
[Edit]
I have got an exception: System.ArgumentException: 'options.MaxSize must be set if overwrite is set to true' Is there any way to avoid specyfining this size?
Please try to use the latest package Azure.Storage.Files.Shares, version 12.5.0.
Note, in the code new ShareFileClient(), the last parameter is the directory name + file name.
see the code below:
ShareFileClient f2 = new ShareFileClient(connectionString, shareName, dirName + "/test.txt");
if (!f2.Exists())
{
f2.Create(0);
}
The file with 0 size can be created, here is the test result:
Micro$ofts infinite wisdom: resize is hidden in SetHttpHeaders method.
public void AppendFile(string filePath, byte[] data)
{
ShareFileClient fileShare = new ShareFileClient(connectionString, shareClient.Name, filePath);
if (!fileShare.Exists())
fileShare.Create(0);
for (int i = 0; i < 10; i++)
{
var properties = fileShare.GetProperties();
var openOptions = new ShareFileOpenWriteOptions();
fileShare.SetHttpHeaders(properties.Value.ContentLength + data.Length);
var stream = fileShare.OpenWrite(false, properties.Value.ContentLength, openOptions);
stream.Write(data, 0, data.Length);
stream.Flush();
}
}
I know that this is may be a question without one 'right' answer
I have a C# windows application that has an embedded resource included in the assembly. I've been trying to come up with a way to compare the contents of my resource stream to determine if the contents of that stream matches a particular file on the file system.
e.g.
using(var resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(#"Manifest/Resource/Path/thing.exe"))
using(var fileStream = new FileStream(#"File/System/Path/thing.exe", FileMode.Read))
// Compare Contents (thing.exe may be an older version)
if(CompareStreamContents(resourceStream, fileStream))
{
/* Do a thing */
}
else
{
/* Do another thing*/
}
Is there a better way than simply doing a byte-by-byte comparison? Thoughts? (and thanks in advance!)
Per my comment:
private bool CompareStreamContents(Stream resourceStream, Stream fileStream)
{
var sha = new SHA256CryptoServiceProvider();
var hash1 = Convert.ToBase64String(sha.ComputeHash(ReadToEnd(resourceStream)));
var hash2 = Convert.ToBase64String(sha.ComputeHash(ReadToEnd(fileStream)));
return hash1 == hash2;
}
private byte[] ReadToEnd(Stream stream)
{
var continueRead = true;
var buffer = new byte[0x10000];
var ms = new MemoryStream();
while (continueRead)
{
var size = stream.Read((byte[])buffer, 0, buffer.Length);
if (size > 0)
{
ms.Write(buffer, 0, size);
}
else
{
continueRead = false;
}
}
return ms.ToArray();
}
If you plan on doing something else with the streams after the compare, you may want to set the stream position back to origin before returning from the compare method.
I'm working on a little C# ASP.NET web app that pulls 3 files from my server, creates a zip of those files, and sends the zip file to an e-mail recipient.
The problem I'm having is finding a way to combine those 3 files without creating a zip file on the hard drive of the server. I think I need to use some sort of memorystream or filestream, but I'm in a little beyond my understanding when it comes to merging them into 1 zip file. I've tried SharpZipLib and DotNetZip, but I haven't been able to figure it out.
The reason I don't want the zip saved locally is that there might be a number of users on this app at once, and I don't want to clog up my server machine with those zips. I'm looking for 2 answers, how to zip files without saving the zip as a file, and how to attach that zip to a MailMessage.
Check this example for SharpZipLib:
https://github.com/icsharpcode/SharpZipLib/wiki/Zip-Samples#wiki-anchorMemory
using ICSharpCode.SharpZipLib.Zip;
// Compresses the supplied memory stream, naming it as zipEntryName, into a zip,
// which is returned as a memory stream or a byte array.
//
public MemoryStream CreateToMemoryStream(MemoryStream memStreamIn, string zipEntryName) {
MemoryStream outputMemStream = new MemoryStream();
ZipOutputStream zipStream = new ZipOutputStream(outputMemStream);
zipStream.SetLevel(3); //0-9, 9 being the highest level of compression
ZipEntry newEntry = new ZipEntry(zipEntryName);
newEntry.DateTime = DateTime.Now;
zipStream.PutNextEntry(newEntry);
StreamUtils.Copy(memStreamIn, zipStream, new byte[4096]);
zipStream.CloseEntry();
zipStream.IsStreamOwner = false; // False stops the Close also Closing the underlying stream.
zipStream.Close(); // Must finish the ZipOutputStream before using outputMemStream.
outputMemStream.Position = 0;
return outputMemStream;
// Alternative outputs:
// ToArray is the cleaner and easiest to use correctly with the penalty of duplicating allocated memory.
byte[] byteArrayOut = outputMemStream.ToArray();
// GetBuffer returns a raw buffer raw and so you need to account for the true length yourself.
byte[] byteArrayOut = outputMemStream.GetBuffer();
long len = outputMemStream.Length;
}
Try this:
public static Attachment CreateAttachment(string fileNameAndPath, bool zipIfTooLarge = true, int bytes = 1 << 20)
{
if (!zipIfTooLarge)
{
return new Attachment(fileNameAndPath);
}
var fileInfo = new FileInfo(fileNameAndPath);
// Less than 1Mb just attach as is.
if (fileInfo.Length < bytes)
{
var attachment = new Attachment(fileNameAndPath);
return attachment;
}
byte[] fileBytes = File.ReadAllBytes(fileNameAndPath);
using (var memoryStream = new MemoryStream())
{
string fileName = Path.GetFileName(fileNameAndPath);
using (var zipArchive = new ZipArchive(memoryStream, ZipArchiveMode.Create))
{
ZipArchiveEntry zipArchiveEntry = zipArchive.CreateEntry(fileName, CompressionLevel.Optimal);
using (var streamWriter = new StreamWriter(zipArchiveEntry.Open()))
{
streamWriter.Write(Encoding.Default.GetString(fileBytes));
}
}
var attachmentStream = new MemoryStream(memoryStream.ToArray());
string zipname = $"{Path.GetFileNameWithoutExtension(fileName)}.zip";
var attachment = new Attachment(attachmentStream, zipname, MediaTypeNames.Application.Zip);
return attachment;
}
}
I want to send a binary file to .net c# component in the following xml format
<BinaryFileString fileType='pdf'>
<!--binary file data string here-->
</BinaryFileString>
In the called component I will use the above xml string and convert the binary string received within the BinaryFileString tag, into a file as specified by the filetype='' attribute. The file type could be doc/pdf/xls/rtf
I have the code in the calling application to get out the bytes from the file to be sent. How do I prepare it to be sent with xml tags wrapped around it? I want the application to send out a string to the component and not a byte stream. This is because there is no way I can decipher the file type [pdf/doc/xls] just by looking at the byte stream. Hence the xml string with the filetype attribute. Any ideas on this?
method for extracting Bytes below
FileStream fs = new FileStream(_filePath, FileMode.Open, FileAccess.Read);
using (Stream input = fs)
{
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0)
{}
}
return buffer;
Thanks.
Edit:
Just to clarify why I am using an xml string rather than setting properties on my component. Actually my calling app is trying to simulate how Siebel will call my component.
http://download.oracle.com/docs/cd/E05553_01/books/eScript/eScript_JSReference244.html#wp1014380
Im not sure if Siebel can set my components properties as I need it to. So Im working on the angle of it sending the data in xml.
Base64 representation is universaly used to represent binary data.
public void EncodeWithString() {
System.IO.FileStream inFile;
byte[] binaryData;
try {
inFile = new System.IO.FileStream(inputFileName,
System.IO.FileMode.Open,
System.IO.FileAccess.Read);
binaryData = new Byte[inFile.Length];
long bytesRead = inFile.Read(binaryData, 0,
(int)inFile.Length);
inFile.Close();
}
catch (System.Exception exp) {
// Error creating stream or reading from it.
System.Console.WriteLine("{0}", exp.Message);
return;
}
// Convert the binary input into Base64 UUEncoded output.
string base64String;
try {
base64String =
System.Convert.ToBase64String(binaryData,
0,
binaryData.Length);
}
catch (System.ArgumentNullException) {
System.Console.WriteLine("Binary data array is null.");
return;
}
// Write the UUEncoded version to the XML file.
System.IO.StreamWriter outFile;
try {
outFile = new System.IO.StreamWriter(outputFileName,
false,
System.Text.Encoding.ASCII);
outFile.Write("<BinaryFileString fileType='pdf'>");
outFile.Write(base64String);
outFile.Write("</BinaryFileString>");
outFile.Close();
}
catch (System.Exception exp) {
// Error creating stream or writing to it.
System.Console.WriteLine("{0}", exp.Message);
}
}
At the receiving end you can reverse this and get back original file content as mentioned below.
// Convert the Base64 UUEncoded input into binary output.
byte[] binaryData;
try {
binaryData =
System.Convert.FromBase64String(base64String);
}
catch (System.ArgumentNullException) {
System.Console.WriteLine("Base 64 string is null.");
return;
}
catch (System.FormatException) {
System.Console.WriteLine("Base 64 string length is not " +
"4 or is not an even multiple of 4." );
return;
}
Can you BASE64 your bytes? MSDN ref: Convert.ToBase64, Convert.FromBase64String
expanding on #russau's answer it will work like this:
var s = "Hello World";
var b = Encoding.Default.GetBytes(s);
var bstr = Convert.ToBase64String(b);
Console.WriteLine("Original String:" + s);
Console.WriteLine("Base64 String:" + bstr);
var fromBStr = Convert.FromBase64String(bstr);
var st = Encoding.Default.GetString(fromBStr);
Console.WriteLine("Converted string: " + st);
you wont need first two lines:
var s = "Hello World";
var b = Encoding.Default.GetBytes(s);
as you already have a byte array. I've used string to show that you get exactly the same value you started with in the end when you convert byte array from Convert.FromBase64String
You mention that you are calling a C# component. I'm not sure I understand why using this component means you need to create an XML string.
Is it possible to define classes to hold your data instead of using an XML string? e.g.
public enum FileType
{
Word,
Excel,
RichText,
PDF
}
public class FileData
{
public FileType TypeOfFile
{
get;
set;
}
public byte[] Data
{
get;
set;
}
}
Then the caller of the component just sets the FileType and the byte[]. The component's interface would then be more explicitly defined (FileData class as opposed to the more generic string or XmlDocument).