CRM saves attachements in AnnotationBase base table.
How can I convert the text in the DocumentBody entity back to file and save it the file system?
I have got the value of the documentbody field and then try to write it in my computer but my is file corrupted.
I am using this code:
String DocumentBody = Convert.ToBase64String(
newUnicodeEncoding().GetBytes("UEsDBBQABgAIAAAAIQDQf9XuxAEAAE4HAAATAAgCW0NvbnRlbnRfVHlwZXNd Lnh/abtPgp4eu7+W68C2dvLaWtho32sTajdkFmweGeKMQYTD5MrcDFf"));
using (FileStream fs = new FileStream("c:\\1.docx", FileMode.Create, FileAccess.Write))
{
byte[] bytes = Convert.FromBase64String(DocumentBody);
fs.Write(bytes, 0, bytes.Length);
}
The string in GetBytes is the same as documentbody field in annotationBase table.
Here is the code that has always worked for me - and I can confirm this has worked for me using data retreived from CRM 4 with the CRM 4 SDK. I did a project almost exactly the same about 18 months ago where we had to archive off all the notes and e-mails from CRM.
If you are still having issues see the original source of this code
public static void ExportFile(string fileName, string content)
{
byte[] fileContent = Convert.FromBase64String(content);
using (FileStream file = new FileStream(fileName, FileMode.Create))
{
using (BinaryWriter writer = new BinaryWriter(file))
{
writer.Write(fileContent,0,fileContent.Length);
writer.Close();
}
file.Close();
}
}
Related
i'm trying to export a email as mht or eml.
The export is working but the content is incomplete.
The Export only contains the content of the green box.
The Content from the red box is missing (sender, recipient, subject, sent).
string emlFileName = #"C:\export\email.eml";
string mhtFileName = #"C:\export\email.mht";
// Save as .eml.
using (FileStream fs = new FileStream(emlFileName, FileMode.Create, FileAccess.Write))
{
fs.Write(email.MimeContent.Content, 0, email.MimeContent.Content.Length);
}
// Save as .mht.
using (FileStream fs = new FileStream(mhtFileName, FileMode.Create, FileAccess.Write))
{
fs.Write(email.MimeContent.Content, 0, email.MimeContent.Content.Length);
}
The application i'm developing needs to compress xml files into zip files and send them through http requests to a web service. As I dont need to keep the zip files, i'm just performing the compression in memory. The web service is denying my requests because the zip files are apparently malformed.
I know there is a solution in this question which works perfectly, but it uses a StreamWriter. My problem with that solution is that StreamWriter requires an encoding or assumes UTF-8, and I do not need to know the enconding of the xml files. I just need to read the bytes from those files, and store them inside a zip file, whatever encoding they use.
So, to be clear, this question has nothing to do with encodings, as I don't need to transform the bytes into text or the oposite. I just need to compress a byte[].
I'm using the next code to test how my zip file is malformed:
static void Main(string[] args)
{
Encoding encoding = Encoding.GetEncoding("ISO-8859-1");
string xmlDeclaration = "<?xml version=\"1.0\" encoding=\"" + encoding.WebName.ToUpperInvariant() + "\"?>";
string xmlBody = "<Test>ª!\"·$%/()=?¿\\|##~€¬'¡º</Test>";
string xmlContent = xmlDeclaration + xmlBody;
byte[] bytes = encoding.GetBytes(xmlContent);
string fileName = "test.xml";
string zipPath = #"C:\Users\dgarcia\test.zip";
Test(bytes, fileName, zipPath);
}
static void Test(byte[] bytes, string fileName, string zipPath)
{
byte[] zipBytes;
using (var memoryStream = new MemoryStream())
using (var zipArchive = new ZipArchive(memoryStream, ZipArchiveMode.Create, leaveOpen: false))
{
var zipEntry = zipArchive.CreateEntry(fileName);
using (Stream entryStream = zipEntry.Open())
{
entryStream.Write(bytes, 0, bytes.Length);
}
//Edit: as the accepted answer states, the problem is here, because i'm reading from the memoryStream before disposing the zipArchive.
zipBytes = memoryStream.ToArray();
}
using (var fileStream = new FileStream(zipPath, FileMode.OpenOrCreate))
{
fileStream.Write(zipBytes, 0, zipBytes.Length);
}
}
If I try to open that file, I get an "Unexpected end of file" error. So apparently, the web service is correctly reporting a malformed zip file. What I have tried so far:
Flushing the entryStream.
Closing the entryStream.
Both flushing and closing the entryStream.
Note that if I open the zipArchive directly from the fileStream the zip file is formed with no errors. However, the fileStream is just there as a test, and I need to create my zip file in memory.
You are trying to get bytes from MemoryStream too early, ZipArchive did not write them all yet. Instead, do like this:
using (var memoryStream = new MemoryStream()) {
// note "leaveOpen" true, to not dispose memoryStream too early
using (var zipArchive = new ZipArchive(memoryStream, ZipArchiveMode.Create, leaveOpen: true)) {
var zipEntry = zipArchive.CreateEntry(fileName);
using (Stream entryStream = zipEntry.Open()) {
entryStream.Write(bytes, 0, bytes.Length);
}
}
// now, after zipArchive is disposed - all is written to memory stream
zipBytes = memoryStream.ToArray();
}
If you use a memory stream to load your text you can control the encoding type and it works across a WCF service. This is the implementation i am using currently and it works on my WCF services
private byte[] Zip(string text)
{
var bytes = Encoding.UTF8.GetBytes(text);
using (var msi = new MemoryStream(bytes))
using (var mso = new MemoryStream())
{
using (var gs = new GZipStream(mso, CompressionMode.Compress))
{
CopyTo(msi, gs);
}
return mso.ToArray();
}
}
private string Unzip(byte[] bytes)
{
using (var msi = new MemoryStream(bytes))
using (var mso = new MemoryStream())
{
using (var gs = new GZipStream(msi, CompressionMode.Decompress))
{
CopyTo(gs, mso);
}
return Encoding.UTF8.GetString(mso.ToArray());
}
}
I have a JSON file created, and I am going to zip it using DotNetZip.
Using with StreamWriter to zip it is working, if I try to use MemoryStream it will not working.
StreamWriter :
sw = new StreamWriter(assetsFolder + #"manifest.json");
sw.Write(strManifest);
sw.Close();
zip.AddFile(Path.Combine(assetsFolder, "manifest.json"), "/");
zip.AddFile(Path.Combine(assetsFolder, "XXXXXXX"), "/");
zip.Save(outputStream);
MemoryStream :
var manifestStream = GenerateStreamFromString(strManifest);
public static Stream GenerateStreamFromString(string s)
{
MemoryStream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
writer.Write(s);
writer.Flush();
stream.Position = 0;
return stream;
}
zip.AddEntry("manifest.json", manifestStream);
zip.AddFile(Path.Combine(assetsFolder, "XXXXXXX"), "/");
zip.Save(outputStream);
I must using the .JSON file type to zip it, Can any one told me where have a mistake?
To create a Gzipped Json you need to use GZipStream. Try method below.
https://www.dotnetperls.com/gzipstream
GZipStream compresses data. It saves data efficiently—such as in
compressed log files. We develop a utility method in the C# language
that uses the System.IO.Compression namespace. It creates GZIP files.
It writes them to the disk.
public static void CompressStringToFile(string fileName, string value)
{
// A.
// Write string to temporary file.
string temp = Path.GetTempFileName();
File.WriteAllText(temp, value);
// B.
// Read file into byte array buffer.
byte[] b;
using (FileStream f = new FileStream(temp, FileMode.Open))
{
b = new byte[f.Length];
f.Read(b, 0, (int)f.Length);
}
// C.
// Use GZipStream to write compressed bytes to target file.
using (FileStream f2 = new FileStream(fileName, FileMode.Create))
using (GZipStream gz = new GZipStream(f2, CompressionMode.Compress, false))
{
gz.Write(b, 0, b.Length);
}
}
Is DeflateStream supposed to create archived stream that can be stored as standard .zip archive?
I'm trying to create in-memory zip (to be sent remotely) from a local file.
I used a DeflateStream to get a compressed byte array from the file on local disk:
public static byte[] ZipFile(string csvFullPath)
{
using (FileStream csvStream = File.Open(csvFullPath, FileMode.Open, FileAccess.Read))
{
using (MemoryStream compressStream = new MemoryStream())
{
using (DeflateStream deflateStream = new DeflateStream(compressStream, CompressionLevel.Optimal))
{
csvStream.CopyTo(deflateStream);
deflateStream.Close();
return compressStream.ToArray();
}
}
}
}
This works great.
However when I dump the resulting bytes to a zip file:
byte[] zippedBytes = ZipFile(FileName);
File.WriteAllBytes("Sample.zip", zippedBytes);
I cannot open the resulting .zip archive with windows build-in .zip functionality (or with any other 3rd party archive tool).
An alternative I'm planning now is using ZipArchive - however that would require creating temporary files on disk (first copy the file into separate directory, then zip it, then read it into byte array and then delete it)
You can use this nice library https://dotnetzip.codeplex.com/
or you can use ZipArchive and it works with MemoryStream pretty good:
public static byte[] ZipFile(string csvFullPath)
{
using (FileStream csvStream = File.Open(csvFullPath, FileMode.Open, FileAccess.Read))
{
using (MemoryStream zipToCreate = new MemoryStream())
{
using (ZipArchive archive = new ZipArchive(zipToCreate, ZipArchiveMode.Create, true))
{
ZipArchiveEntry fileEntry = archive.CreateEntry(Path.GetFileName(csvFullPath));
using (var entryStream = fileEntry.Open())
{
csvStream.CopyTo(entryStream);
}
}
return zipToCreate.ToArray();
}
}
}
I truly appreciate your suggestions. I am using MVC3 and I want user to save to his own path by opening a dialog with password protected. Can you guys please help me on this.
Below is my code:
mydoc.GenerateLetter(PdfData);
string WorkingFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
using (MemoryStream m = new MemoryStream())
{
m.Write(mydoc.DocumentBytes, 0, mydoc.DocumentBytes.Length);
m.Seek(0, SeekOrigin.Begin);
string OutputFile = Path.Combine(WorkingFolder, PdfData.Name + ".pdf");
using (Stream output = new FileStream(OutputFile, FileMode.Create, FileAccess.Write, FileShare.None))
{
PdfReader reader = new PdfReader(m);
PdfEncryptor.Encrypt(reader, output, true, "abc123", "secret", PdfWriter.ALLOW_SCREENREADERS);
}
}
If you want to show a Save As dialog so that the user can choose the location to save the PDF file on his computer you could use the Content-Disposition HTTP header and set it to attachment. Also in an ASP.NET MVC application instead of saving the file to the server (which is what your code currently does), you should stream it to the client:
public ActionResult DownloadPdf()
{
var mydoc = ...
mydoc.GenerateLetter(PdfData);
byte[] pdf = mydoc.DocumentBytes;
var reader = new PdfReader(pdf);
using (var encrypted = new MemoryStream())
{
PdfEncryptor.Encrypt(reader, encrypted, true, "abc123", "secret", PdfWriter.ALLOW_SCREENREADERS);
return File(encrypted.ToArray(), "application/pdf", PdfData.Name + ".pdf");
}
}
Now when a user navigates to this controller action /SomeController/DownloadPdf he will be presented with a Save As dialog allowing him to download the encrypted PDF file and store it in a chosen location on his computer.