Document in byte array to local file from Web Client - c#

On user input, I get the byte array from the cloud (Document in various format) and then I save this byte array as a document in included format. The code runs on desktop client and in Web client (the app runs on the server and method is called from web application of the tool)
I have .NET Framework (4.8) Project. Project is extension for BI tool Spotfire. The source code of the projects runs on desktop client and web client as I mentioned. In desktop client I use standard functionality with SaveFileDialog class and it works fine. For Web client I have problem because I cannot open dialogs and cannot save the file to local path because it run on server and web application.
SaveFileDialog save = new SaveFileDialog();
save.FileName = documentName;
switch (documentInfo.type)
{
case MIME_PDF:
save.Filter = "PDF(*.pdf)|*.pdf";
break;
case MIME_DOC:
save.Filter = "Word document|*.doc";
break;
case MIME_DOCX:
save.Filter = "DOCX document|*.docx";
break;
case MIME_XLS:
save.Filter = "XLS document|*.xls";
break;
case MIME_XLSX:
save.Filter = "XLSX document|*.xlsx";
break;
}
if (save.ShowDialog() == DialogResult.OK)
{
byte[] bytes = AWSInvoker.GetS3Document(documentInfo.id);
File.WriteAllBytes(save.FileName, bytes);));
}
This is the code for desktop client. What I need to do in case when it runs on web client:
-> Get the bytes
-> Download it from Web browser to local storage
-> I have to avoid to store content on server storage but directly run downloading from Web Browser
The application is not ASP.NET and I cannot capture this functionality in JavaScript or any other front end framework

Related

Stream file from FTP server using FluentFTP to web client in ASP.NET Core

I have a shared webhosting service which my ASP.NET Core app runs, and an FTP server. I want to serve the files that clients need to download from the site.
I want the files not to be accessible to everyone, so this is what I do (I use FluentFTP):
var cred = new NetworkCredential(_config.UserName, _config.Password);
FtpClient client = new FtpClient(_config.Host, int.Parse(_config.Port), cred);
await client.ConnectAsync();
var remotePath = $"{_config.Folder}{FILE_DIR}/{filename}";
var result = await client.DownloadAsync(remotePath: remotePath, 0L);
await client.DisconnectAsync();
if (result != null)
{
return File(result, "application/force-download", filename)
}
else
{
throw new Exception("Failed");
}
The problem is, the server tries to download the file from the FTP server, then sends it to client. And there is the same problem for upload too, the client needs to upload file to the server, and then server uploads it to the FTP server. I think this can be very time-consuming with large files.
Is there any better way to achieve this goal? Or is it possible to write the file being downloaded from FTP simultaneously to the client response so the client downloads any bit of file downloaded in server and doesn't have to wait for the download to server to finish to start the download?
Thanks in advance.
Download the file directly to the HTTP output stream with use of FtpClient.Download (to be renamed FtpClient.DownloadStream in upcoming versions) and HttpResponse.OutputStream:
Response.AddHeader("Content-Disposition", $"attachment; filename={filename}");
client.Download(Response.OutputStream, remotePath);
(where Response is ASP.NET HttpResponse).
A similar question for native .NET FtpWebRequest/WebClient:
Download file from FTP and how prompt user to save/open file in ASP.NET C#
Also note that the application/force-download seems like a hack.
Use Content-Disposition: attachment to force the download.

Saving an image file to the IIS Server - ASP.NET - GDI+ error, IIS LOCAL

I'm not too experienced in ASP.NET, but this is what I am trying to achieve - and by the way it works lovely in IIS Express.
An image, delivered in a Byte[] by a WCF Service, is being rendered to a webpage every second or so. The very first image is being saved on the server in the folder "Thumbnails" off the application root (the page that does the saving is in the folder "RestrictedAccess" off the application root) . This works fine in IIS Express, but I'm having serious difficulties when it comes to running it from my local IIS Server.
My first problem is the saving of the image. When I attach to the IIS process, the folder it is trying to save the image in is not the folder I expect (i.e. wwwroot/MyWebsite/Thumbnails) but the PROJECT folder i.e "c:\development\MyWebSite\Thumbnails")
Secondly, when it attempts to save the image, I get a "general error occurred in GDI+". I'm pretty sure this is due to the path, but how do I get it to save in the correct (wwwroot..../thumbnails) folder?
Here's my source
string imageStr = Convert.ToBase64String((byte[])mimicImage);
imMimic.Src = String.Format("data:image/jpg;base64,{0}{1}", imageStr, "");
lbServiceResponse.Text = String.Format("Service response : {0}", "OK");
//
// Update thumbnail ?
if (string.IsNullOrEmpty(mimicData.ThumbNail))
{
mimicData.ThumbNail = String.Format("../ThumbNails/Thumbnail_{0}.jpg", mimicData.ID);
string thumbNailFile = HttpContext.Current.Server.MapPath(#"~\ThumbNails\") + string.Format("Thumbnail_{0}.jpg", mimicData.ID);
//
// Write image to disk
using (MemoryStream ms = new MemoryStream(mimicImage))
{
// Bitmap object
Bitmap bmp = new Bitmap(ms);
bmp.Save(thumbNailFile, ImageFormat.Jpeg);
bmp.Dispose();
}
//
// Update service
_client.UpdateMimicThumbNail(MimicID, mimicData);
}
I've been struggling with this for best part of a day (I'm new to ASP.NET and the whole IIS stuff), so any help would be appreciated.
Thanks
p.s. The Web App is running in its own application pool with ApplicationPoolidentity.

ShellClass.BrowseForFolder(...) DialogBox not showing

I have a .aspx page in my project inside that there is one <a> link for download .txt files.
Am using Shell32.ShellClass and Shell32.Folder2 for showing Browse For Folder for ask user to Where do you want to save files instead it download on default Downloads folder.
Below is my C# code for showing DialogBox.
Shell32.ShellClass shell = new Shell32.ShellClass();
Shell32.Folder2 flder = (Shell32.Folder2)shell.BrowseForFolder(0, "Select destination folder", 0,"Desktop");
if (flder == null)
{
dlgResult = DialogResult.Cancel;
}
else
{
strPath = flder.Self.Path;
dlgResult = DialogResult.OK;
File.WriteAllText(strPath + "\\NewFile.txt", "file content abc tex...");
}
Problem: Above code working fine in Local but when I host website on IIS it's not working and not showing DialogBox.
Is there any specific Settings or Configurations in IIS for that ? or why it's not working when it host in IIS?
please give me suggestions.
Thanks.
Your C# code runs on the server, not in the web page. When you open a dialog box in this way, it runs in the context of the calling code. When running as part of IIS express (or any web server running as you), it opens in your Windows desktop because it is running as you. When running in IIS, it is running as a different account not attached to your desktop, so it will not show.
I am not aware of a way to invoke the "Save As" functionality to save a file to a different folder in JavaScript. The execCommand function may work but it varies from browser to browser. Some versions of Internet Explorer also limit what file types can be downloaded this way.

A default path when downloading PDF file in computer/mobile phone

I created a PDF webapp where users are able to generate various type of PDF on both the computer and mobile phone. However, i run my program on a localhost and this is how i save my PDF based on my computer's file directory
var output = new FileStream(Path.Combine("C:\\Users\\apr13mpsip\\Downloads", filename), FileMode.Create);
However, when i publish my webapp onto azure, i wasn't able to download from both my computer and mobile phone. Therefore i believe that it could be due to my default file directory.
Hence i would like to ask how to do a default file directory for all computer and mobile phone?
Or could it be i left out something that is necessary when the webapp is published online
Thanks.
PS : I hardcoded a default file path in order for me to test my application on a localhost to ensure a perfect working condition. Therefore i'm finding a way to find a default common file directory for all mobile/computer users when they attempt to download the PDF instead of my usual hard-coded file path
UPDATE
I tried using the method Server.MapPath but receive some error.
var doc1 = new Document();
var filename = Server.MapPath("~/pdf") + "MyTestPDF" + DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".pdf";
// var output = new FileStream(Path.Combine("C:\\Users\\apr13mpsip\\Downloads", filename), FileMode.Create);
//iTextSharp.text.pdf.PdfWriter.GetInstance(doc1, output);
using (var output = File.Create(filename))
{
iTextSharp.text.pdf.PdfWriter.GetInstance(doc1, output);
}
doc1.Open();
This is the error i received
ObjectDisposedException was unhandled by user code
Cannot access a closed file.
When you write a Web Application you shall never use hard coded paths, and the last place where you should save files is C:\Users !! It does not matter whether this is Azure or not. It is general rule for any kind of web applications!
In your case I suggest that you create a folder within your application named pdf or something like that and save files there with the following code:
var fileName = Server.MapPath("~/pdf") + filename;
using (var output = File.Create(fileName) )
{
// do what you want with that stream
// usually generate the file and send to the end user
}
However there is even more efficient way. Use the Response.OutputStream and write the resulted PDF directly to the response. Will save you a lot of space on the local server, and the logic to delete unused generated files.

Moving files on the server side using webservice

I am working on a requirement that has the following logic. code is in C# and .NET CF 3.5
Upload some files from a mobile device to a web server.
when the upload is successful, the file is moved to an archived folder on the mobile device.
Download some files from the server to the mobile device.
When the download is successful, the file has to be moved to an archived folder on the server side in order so as not to download the same file again.
Wrote a web service (asmx) to handle this operation. The uploading and downloading works fine.
The webservice uses the function FileInfo.MoveTo() to move the file from the downloaded folder to the archives on the web server.
This works locally fine (when the webservice and the client calling the webservice are hosted on the same machine) but when deployed to a server, I get this message "the process cannot access the file because it is being used by another process".
I have given the necessary permissions to the IIS account on the server side. I would like to know if that can be achieved at all from the mobile device or is there any other way to invoke that call on the mobile device. I need to execute this method immediately after the file is downloaded.
Sample code is attached.
fileEntriesD = SomeWebService.FilesList();
string[] extractedFiles = fileEntriesD.Split(',');
foreach (string fileName in extractedFiles)
{
//dothe file downloading
//code comes here.......
}
//move the file on the server once all the files are downloaded
foreach (string DumpfileName in extractedFiles)
{
//after the download is complete move the file to the archived folder
string MoveFileOnServerStatus;
MoveFileOnServerStatus = SomeWebService.MoveFileToArchive(DumpfileName);
MessageBox.Show(MoveFileOnServerStatus);
}
code for the WebMethod for MoveFileToArchive(DumpfileName)
[WebMethod(Description="move the file to the archive location")]
public string MoveFileToArchive(string fileArchiveName)
{
try
{
string SerPathD = GetLocationOfFiles + "\\" + "ArchivedDispatchedFiles";
FileInfo MFTA = new FileInfo(SerPathD + "\\" + fileArchiveName);
MFTA.MoveTo(SerPathD + "\\" + fileArchiveName);
}
catch(IOException ex)
{
//if there is any error then return the error message.
return ex.Message.ToString();
}
//if the moving was successful then return 1 to the client.
return "1";
}

Categories