How to get jpg file from CloudFiles on Rackspace using openstack.net - c#

I'm running the below code in my controller in an asp.net mvc project. I want to enable the user to view or download the files that I store on Cloud Files on rackspace.
var identity =
new CloudIdentity()
{
Username = "username",
APIKey = "apikey"
};
var storage = new CloudFilesProvider(identity);
Stream jpgStream = new MemoryStream();
storage.GetObject("files.container", "1.jpg", jpgStream);
Stream pdfStream = new MemoryStream();
storage.GetObject("files.container", "2.pdf", pdfStream);
var jpgResult = File(jpgStream, "Image/jpg", "1.jpg");
var pdfResult = File(pdfStream, "Application/pdf", "2.pdf");
The above code works when I return pdfResult. I get the correct file. But when I return the jpgResult, the browser downloads 1.jpg as an empty 0KB file.
Am I doing this the right way? Any idea what the problem might be?

Problem solved after I added:
jpgStream.Position = 0;
pdfStream.Position = 0;
Before the File() call. As per the question: File is empty and I don't understand why. Asp.net mvc FileResult
I don't know why this wasn't an issue with the pdf file.

You can also use the GetObjectSaveToFile method.

Related

Azure.Storage.Blog downloading file from Azure Storage container to local path - from ASP.NET Core - file path and mime type?

I have an Azure application built with ASP.NET Core using the MVC pattern. Document uploads are stored in Azure Blob Containers and the C# upload code I wrote is working great.
I am using Azure.Storage.Blobs version 12.14.1
Here is my download blob code:
//get document metadata stored in sql table, id comes from a method param
var document = _unitOfWork.Documents.GetById(id);
if (document == null)
{
throw new FileNotFoundException();
}
//get connection and container from appsettings.json
string connection = _appConfig.AzureStorageConnection;
string containerName = _appConfig.AzureStorageContainer;
//work with blob client
var serviceClient = new BlobServiceClient(connection);
var container = serviceClient.GetBlobContainerClient(containerName);
var fileName = document.UniqueDocumentName;
var blobClient = container.GetBlobClient(document.UniqueDocumentName);
using (FileStream fileStream = System.IO.File.OpenWrite("<path>"))
{
blobClient.DownloadTo(fileStream);
}
After I get to using code to set up the file stream, I don't understand what to pass into the OpenWrite method as a path. This application is a B2C app and so how do I just prompt a user to download the file?
I do get a file download with the above code but the file is called download.xml. That is not the file that should be downloaded. I expected the download file to be an .odt file.
Documentation seems to be very sparse on downloading from Azure Blob Storage
EDIT 1.
I got rid of the FileStream and did this instead:
MemoryStream ms = new MemoryStream();
ms.Position = 0;
blobClient.DownloadTo(ms);
return new FileStreamResult(ms, document.FileType);
I did this instead of using FileStream and returned FileResult instead:
MemoryStream ms = new MemoryStream();
ms.Position = 0;
blobClient.DownloadTo(ms);
return new FileStreamResult(ms, document.FileType);

Web API: Download Multiple Files Separately

I have a Web Api controller method that gets passed document IDs and it should return the document files individually for those requested Ids. I have tried the accepted answer from the following link to achieve this functionality, but it's not working. I don't know where I did go wrong.
What's the best way to serve up multiple binary files from a single WebApi method?
My Web Api Method,
public async Task<HttpResponseMessage> DownloadMultiDocumentAsync(
IClaimedUser user, string documentId)
{
List<long> docIds = documentId.Split(',').Select(long.Parse).ToList();
List<Document> documentList = coreDataContext.Documents.Where(d => docIds.Contains(d.DocumentId) && d.IsActive).ToList();
var content = new MultipartContent();
CloudBlockBlob blob = null;
var container = GetBlobClient(tenantInfo);
var directory = container.GetDirectoryReference(
string.Format(DirectoryNameConfigValue, tenantInfo.TenantId.ToString(), documentList[0].ProjectId));
for (int docId = 0; docId < documentList.Count; docId++)
{
blob = directory.GetBlockBlobReference(DocumentNameConfigValue + documentList[docId].DocumentId);
if (!blob.Exists()) continue;
MemoryStream memStream = new MemoryStream();
await blob.DownloadToStreamAsync(memStream);
memStream.Seek(0, SeekOrigin.Begin);
var streamContent = new StreamContent(memStream);
content.Add(streamContent);
}
HttpResponseMessage httpResponseMessage = new HttpResponseMessage();
httpResponseMessage.Content = content;
httpResponseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
httpResponseMessage.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
httpResponseMessage.StatusCode = HttpStatusCode.OK;
return httpResponseMessage;
}
I tried with 2 or more document Ids but only one file was downloaded and that also is not in the correct format (without extension).
Zipping is the only option that will have consistent result on all browsers. MIME/multipart content is for email messages (https://en.wikipedia.org/wiki/MIME#Multipart_messages) and it was never intended to be received and parsed on the client side of a HTTP transaction. Some browsers do implement it, some others don't.
Alternatively, you can change your API to take in a single docId and iterate over your API from your client for each docId.
I think only way is that you zip your all the files and then download one zip file. I guess you can use dotnetzip package because it is easy to use.
One way is that, you can first save your files on disk and then stream the zip to download. Another way is, you can zip them in memory and then download the file in stream
public ActionResult Download()
{
using (ZipFile zip = new ZipFile())
{
zip.AddDirectory(Server.MapPath("~/Directories/hello"));
MemoryStream output = new MemoryStream();
zip.Save(output);
return File(output, "application/zip", "sample.zip");
}
}

WebAPI to download PowerPoint file using memory stream

I'm having trouble downloading a file with content using a Powerpoint presentation library (Syncfusion). The docs only supply ASP examples, no Web API specifically.
I can save a file to the file system which has the context I add to the Powerpoint.
I can get the API to download a file to the users browser but this Powerpoint is empty.
Syncfusion has a function to save the Powerpoint to a memory stream so I guess my question is what is the correct way to save a file to the users browser with the content from the stream?
I'm using HTTPGet and hitting the link through the browser. Do I need to sent the context-type or anything like that?
Thanks for your help, I can provide what I have so far if that helps.
Kurtis
Edit:
[HttpGet, Route("")]
public HttpResponseMessage Get()
{
var presentation = Presentation.Create();
var firstSlide = presentation.Slides.Add(SlideLayoutType.Blank);
var textShape = firstSlide.AddTextBox(100, 75, 756, 200);
var paragraph = textShape.TextBody.AddParagraph();
paragraph.HorizontalAlignment = HorizontalAlignmentType.Center;
var textPart = paragraph.AddTextPart("Kurtis' Presentation");
textPart.Font.FontSize = 80;
var memoryStream = new MemoryStream();
presentation.Save(memoryStream);
var result = Request.CreateResponse(HttpStatusCode.OK);
result.Content = new StreamContent(memoryStream);
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "export.pptx"
};
return result;
}
This is what I have, the library saves the presentation to the memory stream, you can change the parameter to a string which writes this to a file and there is an option to pass a filename, format and HttpResponse for MVC but I couldn't get this working with my API controller. I kept getting a network error but didn't know why.
Thanks again
I found my problem with the help of others in the comments.
The code above work but I needed to reset the stream position to zero to actually write the data.
memoryStream.Position = 0;
Thanks for those who commented. :-)

Sending Image from C# to Android via JSON

I have images stored in SQL server, and I want to send them to Android app via JSON with other data. What's the best way to do this?
BTW my server side written in ASP Web API(C#).
In other way I want to make my image like this http://myserver/image.jpg
so I can included in my JSON and download it in Android app.
As its not where clear from your question, This Link is the best what I can find for you. In it he is accessing ASP.NET WebAPI and converting all the things to JSON when access or pass it through the Andriod studio
http://hintdesk.com/how-to-call-asp-net-web-api-service-from-android/
and here is a complete series that can help you more
http://www.tutecentral.com/restful-api-for-android-part-1/
Hope this helps
I finally figure it out
This is the code
public HttpResponseMessage getImage(String name)
{
name = name + ".png";
var result = new HttpResponseMessage(HttpStatusCode.OK);
String filePath = HostingEnvironment.MapPath("~/images/"+name);
FileStream fileStream = new FileStream(filePath, FileMode.Open);
Image image = Image.FromStream(fileStream);
MemoryStream memoryStream = new MemoryStream();
image.Save(memoryStream, ImageFormat.Jpeg);
result.Content = new ByteArrayContent(memoryStream.ToArray());
result.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
fileStream.Dispose();
return result;
}

Add PDF file as attachment to TestTrack using SOAP

I have recently started using C# over the past year so I'm somewhat new to this, but can usually hack through things with some effort, but this one is eluding me. We use TestTrack for development bug/issue tracking at our company. I've created a custom windows forms app to be the front-end to TestTrack for one of our departments. It connects using SOAP. I'm not using WPF/WCF and don't want to go that route. I'm having difficulty finding any examples of how to correctly encode a file for attachment that is a PDF. The code below does actually create an attachment in TestTrack to an already-existing issue, but when you try to open it in TestTrack, it pops up an error message that says "Insufficient Data For An Image". The example below does work if you're wanting to add a text file to TestTrack using SOAP. I'm wanting to know what I need to change below so that I can get a PDF file into TestTrack and then be able to open it in the TestTrack application without the error mentioned above. Thanks in advance for any input/help.
public void getAttachments(long lSession, CDefect def)
{
ttsoapcgi cgiengine = new ttsoapcgi();
// Lock the defect for edit.
CDefect lockedDefect = cgiengine.editDefect(lSession, def.recordid, "", false);
string attachment = "c:\\TEST\\TEST_PDF.PDF";
CFileAttachment file = new CFileAttachment();
file.mstrFileName = Path.GetFileName(attachment);
System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
StreamReader reader = new StreamReader(attachment);
file.mstrFileName = Path.GetFileName(attachment);
file.mpFileData = enc.GetBytes(reader.ReadToEnd());
reader.Close();
CReportedByRecord reprec = lockedDefect.reportedbylist[0];
CFileAttachment[] afile = reprec.attachmentlist;
if (afile == null)
{
lockedDefect.reportedbylist[0].attachmentlist = new CFileAttachment[1];
lockedDefect.reportedbylist[0].attachmentlist[0] = file;
}
// Save our changes.
cgiengine.saveDefect(lSession, lockedDefect);
}
}
Here is the modified method that allowed me to attach a PDF to SOAP and get it into TestTrack as an attachment to an issue:
public void getAttachments(long lSession, CDefect def)
{
ttsoapcgi cgiengine = new ttsoapcgi();
// Lock the defect for edit.
CDefect lockedDefect = cgiengine.editDefect(lSession, def.recordid, "", false);
string attachment = "c:\\TEST\\TEST_PDF.PDF";
CFileAttachment file = new CFileAttachment();
file.mpFileData = File.ReadAllBytes(attachment);
file.mstrFileName = Path.GetFileName(attachment);
CReportedByRecord reprec = lockedDefect.reportedbylist[0];
CFileAttachment[] afile = reprec.attachmentlist;
if (afile == null)
{
lockedDefect.reportedbylist[0].attachmentlist = new CFileAttachment[1];
lockedDefect.reportedbylist[0].attachmentlist[0] = file;
}
// Save our changes.
cgiengine.saveDefect(lSession, lockedDefect);
}

Categories