Moving files on the server side using webservice - c#

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";
}

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.

C# Windows Services File Move to different directory

Apparently changing codes blows my head.
Here's what i am facing at the moment.
I've developed a service that will extract data from an SQL which converts the data into a CSV file and then upload the file via WinSCP. Once upload finishes , the file is then moved to another directory.
However we had an upgrade and i no longer able to extract the Data from SQL as user have to manually download the file and put into my folder.
I then changed my code to remove the SQL part , and kept sequence starting from the Upload file via WinSCP.
However , now my file move no longer works with error :
File Name couldnt be changed because : Could not find file 'Q:\FrontOffice\Nights\Qualtrics\UNPROCESSED\import-contacts.csv'.
Is there any reason why it cannot find that file when the file and path exist?
Note 1 : The Windows Services is installed in a Server environment. The Server has access to the network drive with admin credentials.
Note 2 : User only need to place the file into Unprocessed folder while the service will process the file and move it to Processed folder.
Here is my previous file move code :
string attachFileLoc = AppDomain.CurrentDomain.BaseDirectory + "\\Logs\\import-contacts-"+ DateTime.Today.AddDays(-1).ToString("yyyyMMdd") + ".csv";
var filename = Path.GetFileName(attachFileLoc);
try
{
System.IO.File.Move(#"C:\Users\Administrator\Documents\Automation\csvfiles\import-contacts.csv", attachFileLoc);
WriteToFile("New File name is : " + filename);
}
catch (System.Exception ex)
{
WriteToFile("File Name couldnt be changed because : " + ex.Message);
}
I then modified my code to reflect to our NAS network folder.
string attachFileLoc = #"Q:\FrontOffice\Nights\Qualtrics\PROCESSED\import-contacts-" + DateTime.Today.AddDays(-1).ToString("yyyyMMdd") + ".CSV";
try
{
System.IO.File.Move(#"Q:\FrontOffice\Nights\Qualtrics\UNPROCESSED\import-contacts.csv", attachFileLoc);
WriteToFile("New File name is : " + filename);
}
catch (System.Exception ex)
{
WriteToFile("File Name couldnt be changed because : " + ex.Message);
}
I then tried to use other methods to obtain file location and name
string[] qfile = Directory.GetFiles(#"Q:\FrontOffice\Nights\Qualtrics\UNPROCESSED\", "*.CSV").FirstOrDefault();
try
{
System.IO.File.Move(qfile[0], attachFileLoc);
WriteToFile("New File name is : " + filename);
}
catch (System.Exception ex)
{
WriteToFile("File Name couldnt be changed because : " + ex.Message);
}
but this one didnt even manage to obtain file name and location.
Edit 1 requested by mjwills :
Edit 2 requested by Caius Jard :
[Solution]
I ran debug and tried to use trycatch method to see what is going on.
Apparently I did not have enough privilege level as per conversation before with others in this thread.
I added the server into Domain as my NAS is also in a domain.
I also added the Windows Services to Log On as a Domain user.
I then proceeded to try removing the mapped drive from the Server. This does not work.
It does work when i have mapped drive or if i do mapping in my code , both while the installed services is in a Server that is in a Domain.
Conclusion :
Windows Services does use mapped drive but windows services authentication is not the same as the User Logged in or the same as the user that has the services installed with.
Solution :
Add LogOn Option to the windows services matching the network drive authentication
i.e : If Network Drive is a NAS in Domain , LogOn option should add Domain ID that has access to the required folder.
i.e2 : If Network Drive is a Shared Folder from PC21 , LogOn option should be an ID that has authentication to the required folder in PC21.

How to write to an iSeries FileShare from ASP.Net

I've written an asp.net webapp that writes a file to a location on our iSeries FileShare.
The path looks like this: \IBMServerAddress\Filepath
This code executes perfectly on my local machine, but fails when it's deployed to my (windows) WebServer.
I understand that i may need to do some sort of impersonation to authenticate access to the IFS, but i'm unsure of how to proceed.
Here's the code i'm working with:
string filepath = "\\\\IBMServerAddress\\uploads\\";
public int SaveToDisk(string data, string plant)
{
//code for saving to disk
StreamWriter stream = null;
stream = File.CreateText(filepath + plant + ".txt"); // creating file
stream.Write(data + "\r\n"); //Write data to file
stream.Close();
return 0;
}
Again, this code executes perfectly on my local machine but does not work when deployed to my Windows WebServer - access to filepath is denied.
Thanks for your help.
EDIT: I've tried adding a network account with the same credentials as the IFS user, created a UNC path (iseries)on IIS7 to map the network drive (using the same credentials) - but receive this error:
Access to the path 'iseries\' is denied.
My understanding of Windows in general is that normally services don't have access to standard network shares like a program being run by a user does.
So the first thing would be to see if you can successfully write to a windows file share from the web server.
Assuming that works, you'll need one of two things in order to write to the IBM i share..
1) An IBM i user ID and password that matches the user ID and password the process is being run under
2) A "guest account" configured on IBM i Netserver
http://www-01.ibm.com/support/knowledgecenter/ssw_ibm_i_71/rzahl/rzahlsetnetguestprof.htm
You might have better luck with using Linux/UNIX based Network File System (NFS) which is supported in both Windows and the IBM i.

FTP virtual paths. How to know real Windows path?

I have shared hosting account on some hosting service provider. So, I can upload pics or something else through FTP. For instance, my ASP .NET binaries are in /mysite.com/www/bin. But how can I set logging to file in my app? I should use real paths for that purpose. I even try just write to current directory, but I can see this log file through FTP. It just writes to some tmp path as I guess, like '' which couldn't be accessed through FTP.
So how can I setup file path for logging?
This is how I try to write to current binaries directory:
using (StreamWriter sw = new StreamWriter(String.Format("{0}{1}{2}", Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "\", "log.txt"), true))
{
sw.WriteLine(DateTime.Now.ToString() + ": " + msg);
sw.WriteLine("------------");
sw.Flush();
sw.Close();
}
It write to some long windows path, which I guess it uses for some temporary storing of binaries.
Assuming your question is "I have FTP server running and serving content of "C:\myFTP\" how can I write log files (i.e. from ASP.Net application) to file available via FTP from the server?"
Answer - just write logs to that "C:\myFTP" location (or whatever location your local FTP server is configured to serve.
I solved it myself. You should use HttpContext.Current.Server.MapPath for that.

Upload Files in C#.net Windows Application

I Want Upload some Files into a Website Host in C#.net Windows Application.what is a Best way To Upload file in Windows Application?
That depends on your server. If it's yours you can make it listen to post requests and upload files through there. If it's not yours there's probably ftp installed, so you can try that.
See here for ftp uploading: http://www.vcskicks.com/csharp_ftp_upload.php
and here for using http post requests: http://en.csharp-online.net/HTTP_Post
i found SVN is the best way so far,
install the client on your local machine and on server. and install the server SNV on your sever.
Server: http://www.visualsvn.com/server/
Client: http://tortoisesvn.net/downloads.html
file upload in C#
HttpPostedFileBase file = this.Request.Files["Upload"];
if (file != null)
{
var fileName = file.FileName;
var fileExtension = Path.GetExtension(fileName);
filePath = fileName.Replace(fileName, emailTemplateImage.token + fileExtension);
var imagepath = Server.MapPath("/Upload/EmailTemplateImage/") + filePath;
if (!System.IO.Directory.Exists(filePath))
{
System.IO.Directory.CreateDirectory(filePath);
}
file.SaveAs(imagepath);
}

Categories