Create DotCMIS IContentStream from local file? - dotcmis

How to create a DotCMIS.Data.IContentStream object from a local file?
The tutorial only describes how to create one from a byte array in memory:
byte[] content = UTF8Encoding.UTF8.GetBytes("Hello World!");
ContentStream contentStream = new ContentStream();
contentStream.FileName = "hello-world.txt";
contentStream.MimeType = "text/plain";
contentStream.Length = content.Length;
contentStream.Stream = new MemoryStream(content);

Stream is actually the standard System.IO.Stream of .NET, so here is how to create a DotCMIS IContentStream from a local file:
ContentStream contentStream = new ContentStream();
contentStream.FileName = "hello-world.txt";
contentStream.MimeType = "text/plain";
contentStream.Stream = File.Open("hello-world.txt", FileMode.Open);
contentStream.Length = contentStream.Stream.Length;

Related

Zipping files and uploading to Azure Blobstorage using filestream

I am creating a website with ASP.NET Core, and I need to take a bunch of files, zip them together and then upload them to Azure Blobstorage.
It succeeds, I get a downloadlink but when I download the file, I just get a "File" that I cannot open with anything.
Here's the code that handles the uploading:
var moduleVersionReleaseFiles = _appDbContext
.ModuleVersionReleaseFile
.Where(x => x.ModuleVersionReleaseId == moduleVersionReleaseId)
.ToList();
string AzureBlobStorageConfig = _configuration["AzureBlobStorage"];
var connectionString = _configuration["StorageConnectionString"];
string containerName = moduleVersionReleaseId + "-" + Guid.NewGuid().ToString();
BlobServiceClient blobServiceClient = new BlobServiceClient(connectionString);
BlobContainerClient containerClient = await blobServiceClient.CreateBlobContainerAsync(containerName.ToLowerInvariant(), Azure.Storage.Blobs.Models.PublicAccessType.BlobContainer);
BlobClient blobClient = containerClient.GetBlobClient(moduleVersionReleaseId.ToString());
using var stream = new MemoryStream();
using (var archive = new ZipArchive(stream, ZipArchiveMode.Create))
{
foreach (var moduleVersionReleaseFile in moduleVersionReleaseFiles)
{
var entry = archive.CreateEntry(moduleVersionReleaseFile.File);
using (var entryStream = entry.Open())
using (var fileStream = File.OpenRead($"{moduleVersionReleaseFile.Path}\\{moduleVersionReleaseFile.File}"))
{
await fileStream.CopyToAsync(entryStream);
}
}
stream.Position = 0;
await blobClient.UploadAsync(stream, true);
await stream.FlushAsync();
}
return blobClient.Uri.ToString();
I am using Azurite for testing, so I can't log onto the blobstorage and check there.
Why am I not getting a zip file when downloading the file as expected?
The reason you're not able to open the zip file is because it is not getting saved properly. Can you please try with the following code:
using var stream = new MemoryStream();
using (var archive = new ZipArchive(stream, ZipArchiveMode.Create))
{
foreach (var moduleVersionReleaseFile in moduleVersionReleaseFiles)
{
var entry = archive.CreateEntry(moduleVersionReleaseFile.File);
using (var entryStream = entry.Open())
var fileContents = File.ReadAllBytes($"{moduleVersionReleaseFile.Path}\\{moduleVersionReleaseFile.File}"));
using (BinaryWriter zipFileBinary = new BinaryWriter(entryStream))
{
zipFileBinary.Write(fileContents);
}
}
stream.Position = 0;
await blobClient.UploadAsync(stream, true);
}

How to unzip file in Azure File Share using Azure Function?

I have an Azure Storage Account with Azure File share. I want to extract zip archive file to another dir in file share using Azure functions. I wrote this code in C#:
CloudFileDirectory rootDirectory = cloudFileShare.GetRootDirectoryReference();
CloudFileDirectory output = rootDirectory.GetDirectoryReference("output");
CloudFile cloudFile = input.GetFileReference("archive1.zip");
using (var stream = await cloudFile.OpenReadAsync())
{
var file1 = new ZipArchive(stream);
foreach (var zipEntry in file1.Entries)
{
var file2 = output.GetFileReference(zipEntry.Name);
var fileStream = zipEntry.Open();
await file2.UploadFromStreamAsync(fileStream); //error is in this line
}
}
But I got the error:
System.Private.CoreLib: Exception while executing function: HttpTriggerExtract. Microsoft.WindowsAzure.Storage:
Operation is not valid due to the current state of the object.
How to fix this?
Edit: I fix the error using MemoryStream in addition, this code works:
foreach (var zipEntry in file1.Entries) {
var fsz = output.GetFileReference(zipEntry.Name);
using (var ms = new MemoryStream())
{
using (var fileStream = zipEntry.Open())
{
await fileStream.CopyToAsync(ms);
ms.Seek(0, SeekOrigin.Begin);
await fsz.UploadFromStreamAsync(ms);
}
}
Regarding the issue, please refer to the following code (I use package WindowsAzure.Storage 9.3.1 to do that)
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString);
CloudFileClient cloudFileClient = storageAccount.CreateCloudFileClient();
CloudFileShare cloudFileShare = cloudFileClient.GetShareReference("share2");
CloudFileDirectory rootDirectory = cloudFileShare.GetRootDirectoryReference();
CloudFileDirectory input = rootDirectory.GetDirectoryReference("input");
CloudFileDirectory output = rootDirectory.GetDirectoryReference("output");
CloudFile cloudFile = input.GetFileReference("sample.zip");
using (var stream = await cloudFile.OpenReadAsync())
using (var zipArchive = new ZipArchive(stream)) {
foreach (var entry in zipArchive.Entries)
{
if (entry.Length > 0) {
CloudFile extractedFile = output.GetFileReference(entry.Name);
using (var entryStream = entry.Open())
{
byte[] buffer = new byte[16 * 1024];
using (var ms = await extractedFile.OpenWriteAsync(entry.Length))
{
int read;
while ((read = await entryStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
}
}
}
}
}
The above answer helped me for my problem.
With the new Azure Library (12.7.0) you have to code this way:
string srcDir = #"sourcePath";
string destDir = #"sourcePath\testStorageUnzip";
string srcFileName = "AzureStorageZip.zip";
string azureConnectionString = ConfigurationManager.AppSettings["beecloudfileshare_AzureStorageConnectionString"];
StorageSharedKeyCredential credential = BeeFileManager.GetAzureStorageKeyCredential(azureConnectionString);
Uri srcUri = new Uri("https:" + Path.Combine(srcDir, srcFileName).Replace("\\", "/"), UriKind.Absolute);
Uri destDirUri = new Uri("https:" + Path.Combine(destDir).Replace("\\", "/"), UriKind.Absolute);
// Get a reference to the file we created previously
ShareFileClient sourceFile = new ShareFileClient(srcUri, credential);
ShareDirectoryClient shareDirectoryClient = new ShareDirectoryClient(destDirUri,credential);
shareDirectoryClient.CreateIfNotExistsAsync().GetAwaiter().GetResult();
using (var stream = sourceFile.OpenRead())
using (var zipArchive = new ZipArchive(stream))
{
foreach (var entry in zipArchive.Entries)
{
if (entry.Length > 0)
{
//CloudFile extractedFile = output.GetFileReference(entry.Name);
Uri destUri = new Uri("https:" + Path.Combine(destDir, entry.Name).Replace("\\", "/"), UriKind.Absolute);
ShareFileClient extractedFile = new ShareFileClient(destUri, credential);
using (var entryStream = entry.Open())
{
using (MemoryStream ms = new MemoryStream())
{
entryStream.CopyTo(ms);
//
//Sorry I have this part in another method
//
Uri fileUri = new Uri("https:" + Path.GetDirectoryName(filePath).Replace("\\", "/"), UriKind.Absolute);
// Get a reference to the file we created previously
ShareDirectoryClient directory = new ShareDirectoryClient(fileUri, credential);
ShareFileClient file = directory.GetFileClient(Path.GetFileName(filePath));
ms.Seek(0, SeekOrigin.Begin);
file.Create(ms.Length);
file.Upload(ms);
//
//
//
}
}
}
}
}
}

How can I dynamically create Ziparchive in Azure

I have multiple files in my Azure storage account say its Master container, I have created a dynamic container which will have the required files copied from Master Container, and those coped files needed to be zipped inside that created container. See below code, where in I have created the zip archive. Also the zip archive is getting created, but when I download manually and see the files, it seems corrupted (for ex. the actual size of the individual files are more than 1Mb but the files which I get after download seems 22Kb), and File formats would be .ipt, .iam (Autodesk Inventor Files)
CloudBlobContainer destContainer = blobClient.GetContainerReference(AzureContainer);
bool isCreated = destContainer.CreateIfNotExists();
var zipblob = destContainer.GetBlockBlobReference("inputAssembly.zip");
using (var stream = await zipblob.OpenWriteAsync())
using (var zip = new ZipArchive(stream, ZipArchiveMode.Create))
{
foreach (var fileName in inputfile)
{
using (var fileStream = new MemoryStream())
{
if (destContainer.GetBlockBlobReference(fileName).Exists())
{
destContainer.GetBlockBlobReference(fileName).DownloadToStream(fileStream);
}
var newZip = new ZipArchive(fileStream, ZipArchiveMode.Create);
var entry = newZip.CreateEntry(fileName, CompressionLevel.NoCompression);
using (var innerFile = entry.Open())
{
fileStream.CopyTo(innerFile);
}
fileStream.Close();
}
}
}
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference(fixedpartContainer);
CloudBlobContainer destContainer1 = blobClient.GetContainerReference(AzureContainer);
bool isCreated = destContainer1.CreateIfNotExists();
var zipblob = destContainer1.GetBlockBlobReference("inputAssembly.zip");
using (var stream = await zipblob.OpenWriteAsync())
{
using (var zipArchive = new ZipArchive(stream, ZipArchiveMode.Create))
{
foreach (var blobName in blobFileNames)
{
var blob = destContainer.GetBlockBlobClient(blobName);
var zipEntry = zipArchive.CreateEntry(blobName);
using var zipStream = zipEntry.Open();
using var fileStream = new MemoryStream();
await blob.DownloadToAsync(fileStream);
await zipStream.WriteAsync(fileStream.ToArray());
AssemblyCreated = true;
}
}
}

Not able to get excel file from web api dot net core 2.1 using epplus excel package

I'm trying to generate an excel file / stream in my web api and return it in a HttpResponseMessage to serve it to the client in Angular 5 as a download.
The generation succeeds and an xlsx file is generated and saved on the server, but when I return it in the Content of my httpResponseMessage, my browser shows just some json instead of the whole excel file.
{"version":{"major":1,"minor":1,"build":-1,"revision":-1,"majorRevision":-1,"minorRevision":-1},"content":{"headers":[{"key":"Content-Disposition","value":["attachment; filename=636742856488421817.xlsx"]},{"key":"Content-Type","value":["application/ms-excel"]},{"key":"Content-Length","value":["22780"]}]},"statusCode":200,"reasonPhrase":"OK","headers":[],"requestMessage":null,"isSuccessStatusCode":true}
This is how I create the excel file and returns it:
var dataBytes = File.ReadAllBytes(fileName);
var dataStream = new MemoryStream(dataBytes);
HttpResponseMessage httpResponseMessage = new HttpResponseMessage(HttpStatusCode.OK);
httpResponseMessage.Content = new StreamContent(dataStream);
httpResponseMessage.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
httpResponseMessage.Content.Headers.ContentDisposition.FileName = fileName;
httpResponseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/ms-excel");
httpResponseMessage.Content.Headers.ContentLength = dataStream.Length;
I solved this:
Here is what I did
Helper class which creates the excel package and converts it to a Stream
var fileName = DateTime.Now.Ticks + ".xlsx";
FileInfo file = new FileInfo(fileName);
FileInfo templateFile = new FileInfo(#"Templates/ReportTemplate.xlsx");
ExcelPackage package = new ExcelPackage(file, templateFile);
ExcelWorksheet worksheet = package.Workbook.Worksheets.FirstOrDefault();
... filling rows and cells goed here ...
var dataBytes = package.GetAsByteArray();
Stream dataStream = new MemoryStream(dataBytes);
dataStream.Seek(0, SeekOrigin.Begin);
return dataStream;
In the controller I return the file to the Angular client like this:
var stream = _helperClass.GenerateReport(exportDate, exportTitle);
return File(stream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", $"Report-{DateTime.Now.ToShortDateString()}.xlsx");
In the Angular component I do this after I receive the response:
var blob = new Blob([res], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
var blobURL = window.URL.createObjectURL(blob);
var anchor = document.createElement("a");
anchor.download = `Report-${new Date().toISOString()}.xlsx`;
anchor.href = blobURL;
anchor.click();
Try this following code:
For conroller:
[Route("DownLoadExcel")]
public IActionResult DownLoadExcel()
{
var pack = new ExcelPackage();
ExcelWorksheet worksheet = pack.Workbook.Worksheets.Add("sample");
//First add the headers
worksheet.Cells[1, 1].Value = "ID";
worksheet.Cells[1, 2].Value = "Name";
//Add values
worksheet.Cells["A2"].Value = 1000;
worksheet.Cells["B2"].Value = "Jon";
return File(pack.GetAsByteArray(), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "Sample.xlsx");
}
For client side:
window.open("../.../DownLoadExcel");

Uploaded image file in SharePoint cannot be displayed

I'm developing a rather simple visual WebPart for SharePoint Foundation Server 2010.
It's supposed to upload an image file to the SharePoint server and display it afterwards.
While I can successfully upload the file to a previously created document library, the file cannot be displayed (IE shows the red cross). When I upload an exact copy of the file using SharePoint frontend, it can be opened. I hope that someone can tell me what I'm missing.
Below you can find the code that successfully uploads a file to the server:
SPContext.Current.Web.AllowUnsafeUpdates = true;
string path = "";
string[] fileName = filePath.PostedFile.FileName.Split('\\');
int length = fileName.Length;
// get the name of file from path
string file = fileName[length - 1];
SPWeb web = SPContext.Current.Web;
SPFolderCollection folders = web.Folders;
SPFolder folder;
SPListCollection lists = web.Lists;
SPDocumentLibrary library;
SPList list = null;
Guid guid = Guid.Empty;
if (lists.Cast<SPList>().Any(l => string.Equals(l.Title, "SPUserAccountDetails-UserImages")))
{
list = lists["SPUserAccountDetails-UserImages"];
}
else
{
guid = lists.Add("SPUserAccountDetails-UserImages", "Enthält Mitarbeiter-Fotos", SPListTemplateType.DocumentLibrary);
list = web.Lists[guid];
}
library = (SPDocumentLibrary)list;
folder = library.RootFolder.SubFolders.Add("SPUserAccountDetails");
SPFileCollection files = folder.Files;
Stream fStream = filePath.PostedFile.InputStream;
byte[] MyData = new byte[fStream.Length];
Stream stream = new MemoryStream();
stream.Read(MyData, 0, (int)fStream.Length);
fStream.Close();
bool bolFileAdd = true;
for (int i = 0; i < files.Count; i++)
{
SPFile tempFile = files[i];
if (tempFile.Name == file)
{
folder.Files.Delete(file);
bolFileAdd = true;
break;
}
}
if (bolFileAdd)
{
SPFile f = files.Add(file, MyData);
f.Item["ContentTypeId"] = "image/jpeg";
f.Item["Title"] = file;
f.Item.SystemUpdate();
SPContext.Current.Web.AllowUnsafeUpdates = false;
imgPhoto.ImageUrl = (string)f.Item[SPBuiltInFieldId.EncodedAbsUrl];
}
Never mind. My code seems to mess with the file content. I'll post the solution later.
edit:
I'm stupid and sorry :-/
I replaced this:
Stream fStream = filePath.PostedFile.InputStream;
byte[] MyData = new byte[fStream.Length];
Stream stream = new MemoryStream();
stream.Read(MyData, 0, (int)fStream.Length);
fStream.Close();
with this:
Stream fStream = filePath.PostedFile.InputStream;
byte[] MyData = new byte[fStream.Length];
BinaryReader binaryReader = new BinaryReader(fStream);
MyData = binaryReader.ReadBytes((Int32)fStream.Length);
fStream.Close();
binaryReader.Close();
and suddenly it all worked ;-)

Resources