I have a zip file. I want open it with SharpZipLib and add a new ZipEntry to it that it is created in memory.
I am new to SharpZipLib. I googled very much but couldn't find similar problem.
My Sample Code is:
public Stream GetNewZipFileStream(string zipFilePath)
{
byte[] zipFileBytes = null;
zipFileBytes = ReadFileBytes(zipFilePath);
var zipFileMemoryStream = new MemoryStream(zipFileBytes);
ZipOutputStream zipOutStream = new ZipOutputStream(zipFileMemoryStream);
var newEntry = new ZipEntry("NewFile.txt");
zipOutStream.PutNextEntry(newEntry);
var newFileMemoryStream = MakeOnTheFlyStream();
StreamUtils.Copy(newFileMemoryStream , zipOutStream, new byte[4096]);
zipOutStream.CloseEntry();
newFileMemoryStream.Close();
zipOutStream.IsStreamOwner = false;
zipOutStream.Close();
newFileMemoryStream.Position = 0;
return newFileMemoryStream;
}
ReadFileBytes and MakeOnTheFlyStream are my methods.
Related
I am trying to save an image from the Android gallery to a shared folder on a windows server. With the NuGet SharpCifs.Std package installed, I try to use the CopyTo method to save the image but it gives an error when the path is correct to my knowledge.
This is the error
Piece of code ...
using SharpCifs.Smb;
...
...
var windowsAuth = new NtlmPasswordAuthentication("mydomain.local", "user", "password");
var source = new SmbFile(photoFile);
var dest = new SmbFile(photosPath, windowsAuth);
source.CopyTo(dest);
In debug mode, the value of variables are:
source = file:///storage/emulated/0/Android/data/com.salicru/files/Pictures/temp/IMG_20190828_101004_88.jpg
dest = file://srvdoc/compartit/fotos equips/M3/6A0BW000001/
What am I doing wrong?
I had to create a method that I called ConvertMediaFileToByteArray for the conversion of the photo stream to a byte[].
private byte[] ConvertMediaFileToByteArray(MediaFile file)
{
using (var memoryStream = new MemoryStream())
{
file.GetStream().CopyTo(memoryStream);
return memoryStream.ToArray();
}
}
Converting call.
file = await CrossMedia.Current.PickPhotoAsync(new PickMediaOptions
{
PhotoSize = PhotoSize.Small
});
if (file != null)
{
imageSource = ImageSource.FromStream(() =>
{
var stream = file.GetStream();
file.Dispose();
return stream;
});
//Convert ImatgeStream to BYTE[]
var imageToByte = ConvertMediaFileToByteArray(file);
}
Then, instead of using CopyTo method i used CreateNewFile method.
var windowsAuth = new NtlmPasswordAuthentication("domain", "admin", "password");
var dest = new SmbFile(photosPath + imageName, windowsAuth);
dest.CreateNewFile();
var writeStream = dest.GetOutputStream();
writeStream.Write(imageToByte);
writeStream.Dispose();
I am trying to create a new PdfDocument from other PdfDocuments that are created in memory. I can do this by saving them to the disk and then just reading them, but I was wondering if there is a way to do this with just a memory stream? That way I could create the other pieces in memory and just place them into the new pdfdocument. Any help would be appreciated. Below is my attempt to do this with a memory stream but I seem to be missing something.
using (var stream = new MemoryStream())
{
using (var pdfDocument = new PdfDocument(new PdfWriter(stream )))
{
var doc = new Document(pdfDocument, new PageSize(298f, 178f));
doc.SetMargins(0,0,0,0);
var tableInfo = PageElementsFactory.BuildDefaultTable(null, 1);
tableInfo.SetMargin(0);
tableInfo.SetPadding(0);
var cell = PageElementsFactory.BuildDefaultCell();
var dataValue = DataValues[PdfConstValues.RETENTION_INFORMATION_CUSTOMER_NAME];
cell.Add(new Paragraph(dataValue).SetFontSize(12f));
tableInfo.AddCell(cell);
var cell2 = PageElementsFactory.BuildDefaultCell();
cell2.Add(new Paragraph(DataValues[PdfConstValues.RETENTION_INFORMATION_ORDER_INFO]).SetBold());
tableInfo.AddCell(cell2);
var cell3 = PageElementsFactory.BuildDefaultCell();
cell3.Add(new Paragraph(DataValues[PdfConstValues.RETENTION_INFORMATION_PART_NUMBER])
.SetFontSize(23f).SetBold());
tableInfo.AddCell(cell3);
doc.Add(tableInfo);
doc.Close();
var page = pdfDocument.GetFirstPage();
var xObject = page.CopyAsFormXObject(newPdfDocument);
return new Image(xObject);
}
}
mkl gave me a few ideas from his comment, and after some more trial and error all I had to do was close the pdfdocument and then copy the stream to an array and create a new memory stream from it and BAM! it worked.
doc.Add(tableInfo);
doc.Close();
var streamInfo = stream.ToArray();
var memstreamClone = new MemoryStream(streamInfo);
memstreamClone.Position = 0;
var pdfStreamDoc = new PdfDocument(new PdfReader(memstreamClone));
var firstPage = pdfStreamDoc.GetFirstPage();
return new Image(firstPage.CopyAsFormXObject(pdfDoc));
I am working on one demo application (Asp.net MVC) where i want to apply self running and transition time animation on existing Power Points. I wrote below code,
using (var templateFile = System.IO.File.Open(Server.MapPath("~/OurCompanyTeam.pptx"), FileMode.Open, FileAccess.Read))
{
using (var stream = new MemoryStream())
{
templateFile.CopyTo(stream);
using (var presentationDocument = PresentationDocument.Open(stream, true))
{
var presentationPart = presentationDocument.PresentationPart;
var presentation = presentationPart.Presentation;
var slideList = new List<SlidePart>();
foreach (SlideId slideID in presentation.SlideIdList)
{
var slide = (SlidePart)presentationPart.GetPartById(slideID.RelationshipId);
Transition trns = new Transition();
trns.Duration = "2.5";
trns.Speed = TransitionSpeedValues.Fast;
slide.Slide.Transition = trns;
slideList.Add(slide);
}
presentationPart.Presentation.Save();
}
byte[] buffer = stream.ToArray();
MemoryStream ms = new MemoryStream(buffer);
FileStream file = new FileStream(Server.MapPath("~/output.pptx"), FileMode.Create, FileAccess.Write);
ms.WriteTo(file);
file.Close();
}
}
How could i improve this code to set up self running presentation?
The code in this answer will make any presentation(.pptx) a self running Slide Show (.ppsx). It does the following items:
Puts the presentation in kiosk mode
Sets the AdvanceAfterTime attribute to 2 seconds for each slide
Change the Document type to Slide Show
Saves contents of .pptx to a new .ppsx file.
You can replace your code above with the following code. Add a _sourceFile string local variable to save the full path to your file. Notes in the comments for the items above:
using (var templateFile = System.IO.File.Open(Server.MapPath("~/OurCompanyTeam.pptx"), FileMode.Open, FileAccess.Read))
{
using (var stream = new MemoryStream())
{
templateFile.CopyTo(stream);
using (var presentationDocument = PresentationDocument.Open(stream, true))
{
var presentationPart = presentationDocument.PresentationPart;
var presentation = presentationPart.Presentation;
var slideList = new List<SlidePart>();
foreach (SlideId slideID in presentation.SlideIdList)
{
var slidePart = (SlidePart)presentationPart.GetPartById(slideID.RelationshipId);
AlternateContent alternateContent1 = slidePart.Slide.GetFirstChild<AlternateContent>();
if (alternateContent1 != null)
{
slidePart.Slide.RemoveAllChildren<AlternateContent>();
}
var trns1 = new Transition();
trns1.Duration = "2000";
trns1.AdvanceOnClick = false;
trns1.AdvanceAfterTime = "2000"; //ITEM #2
trns1.Speed = TransitionSpeedValues.Slow;
var alternateContent = new AlternateContent();
alternateContent.AddNamespaceDeclaration("mc", "http://schemas.openxmlformats.org/markup-compatibility/2006");
AlternateContentChoice alternateContentChoice = new AlternateContentChoice() { Requires = "p14" };
alternateContentChoice.AddNamespaceDeclaration("p14", "http://schemas.microsoft.com/office/powerpoint/2010/main");
alternateContentChoice.Append(trns1);
alternateContent.Append(alternateContentChoice);
slidePart.Slide.Append(alternateContent);
}
var presentationPropertiesPart = presentationPart.PresentationPropertiesPart;
var presentationProperties = presentationPropertiesPart.PresentationProperties;
presentationProperties.RemoveAllChildren<ShowProperties>();
presentationProperties.Append(NewShowProperties());
presentationDocument.ChangeDocumentType(PresentationDocumentType.Slideshow); //ITEM #3
}
byte[] buffer = stream.ToArray();
MemoryStream ms = new MemoryStream(buffer);
FileStream file = new FileStream(System.IO.Path.GetDirectoryName(_sourceFile) + "/NewSlideShow.ppsx",
FileMode.Create, FileAccess.Write); //ITEM #4
ms.WriteTo(file);
file.Close();
}
}
then add this method at the bottom of your class:
private ShowProperties NewShowProperties()
{
var showProperties = new ShowProperties { Loop = true, ShowNarration = true };
showProperties.Append(new KioskSlideMode()); //ITEM #1
showProperties.Append(new SlideAll());
showProperties.Append(new PresenterSlideMode());
return showProperties;
}
I've tested this to work on newly created PowerPoint 2013 and 2016 Presentations. Double click on the .ppsx file and it will launch the self-running presentation.
Since System.IO.Compression seems to be out of reach for now if I want to use both dotnet core + net461, I've tried with SharpCompress.
The "read zip" part was easy, but I am having trouble finding out how to write to a zip stream.
The wiki of the project is a bit outdated. This is the only example that I've found that applies to writing to streams. I've tried to follow it and adapt it to my needs, but I am stuck at the exception it throws:
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SharpCompress.Common;
using SharpCompress.Compressors.Deflate;
using SharpCompress.Writers;
using System;
using System.IO;
namespace DbManager.DjdbCore.Tests
{
[TestClass]
public class ZipTests
{
public ZipTests()
{
Directory.SetCurrentDirectory(AppContext.BaseDirectory);
}
[TestMethod]
public void Test()
{
var zip = File.OpenWrite(#"..\..\..\..\..\test-resources\zip_file_test.zip");
var writerOptions = new WriterOptions(CompressionType.Deflate);
var zipWriter = WriterFactory.Open(zip, ArchiveType.Zip, writerOptions);
var memoryStream = new MemoryStream();
var binaryWriter = new BinaryWriter(memoryStream);
binaryWriter.Write("Test string inside binary file - text to fill it up: qoiwjqefñlawijfñlaskdjfioqwjefñalskvndñaskvnqo`wiefowainvñaslkfjnwpowiqjfeopwiqjnfjñlaskdjfñlasdfjiowiqjefñaslkdjfñalskjfpqwoiefjqw");
var deflateStream = new DeflateStream(memoryStream, SharpCompress.Compressors.CompressionMode.Compress);
deflateStream.Write(memoryStream.ToArray(), 0, Convert.ToInt32(memoryStream.Length));
// EXCEPTION: SharpCompress.Compressors.Deflate.ZlibException: 'Cannot Read after Writing.'
// Source code: if (_streamMode != StreamMode.Reader) { throw new ZlibException("Cannot Read after Writing."); }
zipWriter.Write("test_file_inside_zip.bin", deflateStream, DateTime.Now);
zip.Flush();
zipWriter.Dispose();
zip.Dispose();
}
}
}
In case it helps, this is what I used (and it worked, but only in dotnet core) using the library System.IO.Compression:
private void WriteAsZipBinary()
{
//Open the zip file if it exists, else create a new one
var zip = ZipPackage.Open(this.FileFullPath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
var zipStream = ZipManager.GetZipWriteStream(zip, nameOfFileInsideZip);
var memoryStream = new MemoryStream();
var binaryWriter = new BinaryWriter(memoryStream);
// Here is where strings etc are written to the binary file:
WriteStuffInBinaryStream(ref binaryWriter);
//Read all of the bytes from the file to add to the zip file
byte[] bites = new byte[Convert.ToInt32(memoryStream.Length - 1) + 1];
memoryStream.Position = 0;
memoryStream.Read(bites, 0, Convert.ToInt32(memoryStream.Length));
binaryWriter.Dispose();
binaryWriter = null;
memoryStream.Dispose();
memoryStream = null;
zipStream.Position = 0;
zipStream.Write(bites, 0, bites.Length);
zip.Close();
}
public static Stream GetZipWriteStream(Package zip, string renamedFileName)
{
//Replace spaces with an underscore (_)
string uriFileName = renamedFileName.Replace(" ", "_");
//A Uri always starts with a forward slash "/"
string zipUri = string.Concat("/", Path.GetFileName(uriFileName));
Uri partUri = new Uri(zipUri, UriKind.Relative);
string contentType = "Zip"; // System.Net.Mime.MediaTypeNames.Application.Zip;
//The PackagePart contains the information:
// Where to extract the file when it's extracted (partUri)
// The type of content stream (MIME type): (contentType)
// The type of compression: (CompressionOption.Normal)
PackagePart pkgPart = zip.CreatePart(partUri, contentType, CompressionOption.Normal);
//Compress and write the bytes to the zip file
return pkgPart.GetStream();
}
I'll post here the answer on github from #adamhathcock (the owner of the project):
[TestMethod]
public void Test()
{
var writerOptions = new WriterOptions(CompressionType.Deflate);
using(var zip = File.OpenWrite(#"..\..\..\..\..\test-resources\zip_file_test.zip"))
using(var zipWriter = WriterFactory.Open(zip, ArchiveType.Zip, writerOptions))
{
var memoryStream = new MemoryStream();
var binaryWriter = new BinaryWriter(memoryStream);
binaryWriter.Write("Test string inside binary file - text to fill it up: qoiwjqefñlawijfñlaskdjfioqwjefñalskvndñaskvnqo`wiefowainvñaslkfjnwpowiqjfeopwiqjnfjñlaskdjfñlasdfjiowiqjefñaslkdjfñalskjfpqwoiefjqw");
memoryStream.Position = 0;
zipWriter.Write("test_file_inside_zip.bin", memoryStream, DateTime.Now);
}
}
2 things:
You forgot to reset the MemoryStream after writing to it so it can be read.
You don't need to manually use the DeflateStream. You've told the ZipWriter what compression to use. If it worked, you would have double compressed the bytes which would be garbage really.
I'm trying to take preexisting pdf files and read them all into a memory stream to then be shown on a telerik pdf viewer. If I just do one file it works but as soon as I try multiple files it gives me a internal null error (object ref not set to blah blah) and can't step in the code to see where its actualy null. Am I doing this wrong or something?
List<string> applicableReports = CurrentWizard.GetApplicableReports();
previousReportsStream = new MemoryStream();
Stream[] streams = new Stream[applicableReports.Count];
for (int i = 0; i < streams.Length; i++)
{
streams[i] = new MemoryStream(DocumentHelper.Instance.ConvertFileToByteArray(applicableReports[i]));
streams[i].CopyTo(previousReportsStream);
}
RadPdfViewer radPdfViewer = new RadPdfViewer();
RadFixedDocument document = new PdfFormatProvider(previousReportsStream, FormatProviderSettings.ReadAllAtOnce).Import();
radPdfViewer.Document = document;
This is where error is thrown:
RadFixedDocument document = new PdfFormatProvider(previousReportsStream, FormatProviderSettings.ReadAllAtOnce).Import();
DocumentHelper File to byte[]:
public byte[] ConvertFileToByteArray(string fileName)
{
FileInfo fileInfo = new FileInfo(fileName);
byte[] fileData = null;
using (FileStream fileStream = new FileStream(fileInfo.FullName, FileMode.Open, FileAccess.Read))
{
BinaryReader binaryReader = new BinaryReader(fileStream);
fileData = binaryReader.ReadBytes((int)fileStream.Length);
}
return fileData;
}
One possible cause is the h process is out of memory because the code creates many MemoryStream object and does not dispose them.
Try change code to this:
List<string> applicableReports = CurrentWizard.GetApplicableReports();
previousReportsStream = new MemoryStream();
try
{
for (int i = 0; i < streams.Length; i++)
{
using( MemoryStream memStream = new MemoryStream(DocumentHelper.Instance.ConvertFileToByteArray(applicableReports[i]))
{
memStream.CopyTo(previousReportsStream);
}
}
RadPdfViewer radPdfViewer = new RadPdfViewer();
RadFixedDocument document = new PdfFormatProvider(previousReportsStream, FormatProviderSettings.ReadAllAtOnce).Import();
radPdfViewer.Document = document;
}
finally
{
previousReportsStream.Close();
}
As MemoryStream implements the IDisposable interface, you call dispose it to free the native resources; if not, the it will lead to high memory usage.
Please read MSDN for more details.