Upload Large Files from ASP .Net Application - asp.net

I am building a website where i need a page where user can upload large video files, i have created WCF service with streaming but i am calling that WCF service from Button_Click event of web page.
I have used below mentioned article for WCF service creation
WCF Streaming
I have used streaming as it should be efficient and should not be buffered in memory of server.
Now questions
1) I am having doubts that the entire file is uploaded to the web server and then it is transferred to WCF Service server...if this is true then i am not getting advantage of streaming as well as iis and web server will be down very soon if user uploads large file or multiple user are uploading files con currently
2) Is there any other efficient way to do same operation with some other technique
Please help me ...
EDIT :
If I am not calling WCF Service method from ASP .Net code in that case also it is transferring bytes to the web server which i have checked with HTTPFox
I have checked above thing with upload control and putting one button on UI whose click event is bound to one method in code behind.
So, still i am having that confusion that how data is transferred
Client Machine - Web Server (ASP .Net Application) - Service Server (WCF Service)
Client Machine - Service Server (WCF Service)
NOTE : If i am putting a debug point on button_click and uploading 10 kb file it hits that in less then 1 sec. but if i am uploading 50 mb file then it is taking time.
I placed code of calling WCF service inside that button_click event

1) I am having doubts that the entire
file is uploaded to the web server and
then it is transferred to WCF Service
server...if this is true then i am not
getting advantage of streaming as well
as iis and web server will be down
very soon if user uploads large file
or multiple user are uploading files
con currently
No, you're confusing stuff here. When you use WCF streaming to upload a large file, the file is being sent in chunks - in blocks of several Kbyte in size. The WCF server - running in IIS or self-hosted in a NT service or a console app - while receive those chunks and write them to disk, as they arrive.
You don't "upload the whole file to the web server" and then "transfer it" to the WCF service - the WCF service itself is receiving and handling the file - and only once.
If you host your WCF service yourself - in a console app, a Winforms app, or a Windows NT Service - there's not even any IIS or web server involved AT ALL. WCF handles it all by itself.
Using WCF streaming is probably one of the most memory efficient and one of the simplest ways to transfer large files to a server.
Check out some more example and blog posts on the topic:
MSDN WCF Streaming Sample
Data Transfer Using Self Hosted WCF Service
Sending Attachments with WCF
Progress Indication while Uploading/Downloading Files using WCF

Here is your best solution, I went the same route as you and concluded ftp is easier and works flawlessly. Here is some example code:
First get this library, works flawlessly:
http://www.freedownloadscenter.com/Programming/Components_and_Libraries/BytesRoad_NetSuit_Library.html
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.IO;
using System.Configuration;
using System.Collections.Specialized;
using System.Drawing;
using System.Drawing.Imaging;
using System.Net;
using BytesRoad.Net.Ftp;
namespace GetMedia
{
class Program
{
static void Main(string[] args)
{
string strPath;
string strThumbPath;
string strThumbLocalPath;
string strURLRoot;
string strVideoFile;
string strThumbfile;
string strError;
BizetDataDataContext db = new BizetDataDataContext();
VCMediaDataContext db2 = new VCMediaDataContext();
db.Connection.ConnectionString = Settings.Default.ConnectionString;
db2.Connection.ConnectionString = Settings.Default.ConnectionString;
//Temp Folder
strPath = Settings.Default.TempFolder;
strThumbLocalPath = Settings.Default.ThumbPath;
download video and thumb
//then upload to mediaserver
IQueryable<BizetInfo> custQuery =
from bizet in db.BizetInfos
where bizet.Path != null
select bizet;
foreach (BizetInfo objbizet in custQuery)
{
//Grab filename and path
strVideoFile = Path.GetFileName(objbizet.Path).Replace("%20", "_").Replace("_medium", "").Replace(" ", "_");
strThumbfile = Path.GetFileName(objbizet.Path).Replace("%20", " ").Replace("_medium.wmv", ".mpg.png");
strURLRoot = objbizet.Path.Replace(Path.GetFileName(objbizet.Path), "");
strThumbPath = strURLRoot + strThumbfile;
strError = "";
try
{
wsViaCastMedia.MediaTransferSoapClient ws = new wsViaCastMedia.MediaTransferSoapClient();
System.Net.WebClient wc = new System.Net.WebClient();
//connect to Bizet
Console.WriteLine("Starting spotID: " + objbizet.SPOTID.ToString().Trim());
Console.WriteLine("connected to ws");
Console.WriteLine("Downloading Video File");
//Download Video
wc.DownloadFile(objbizet.Path, strPath + strVideoFile);
//Download Thumb
Console.WriteLine("Downloading Thumb File");
wc.DownloadFile(strThumbPath, strThumbLocalPath + strThumbfile);
wc.Dispose();
//new ftp code
BytesRoad.Net.Ftp.FtpClient f = new BytesRoad.Net.Ftp.FtpClient();
f.PassiveMode = false;
f.Connect(999999999, "IPADDRESS OF FTP", 21);
f.Login(999999999, "", "");
try
{
f.ChangeDirectory(999999999, objbizet.CLIENTID.ToString().Trim());
}
catch (Exception e)
{
f.CreateDirectory(999999999, objbizet.CLIENTID.ToString().Trim());
f.ChangeDirectory(999999999, objbizet.CLIENTID.ToString().Trim());
Console.WriteLine(e);
}
f.PutFile(999999999, strVideoFile, "E:\\temp\\" + strVideoFile);
Console.WriteLine("Transfer of Video File " + objbizet.Path + " Complete");
//response.Close();
f.Disconnect(999999999);
}
catch (Exception e)
{
Console.WriteLine(e);
strError = e.ToString();
}
finally //Update Data
{
//check if spot Exists ///need to fix
//var myquery = from m in db2.Medias
// where m.SpotID == Convert.ToInt32(objbizet.SPOTID.Trim())
// select m;
//foreach (var mm in myquery)
//{
// //db2.DeleteMedia(objbizet.SPOTID.Trim());
//}
if (strError == "")
{
db2.AddMedia(Convert.ToInt32(objbizet.SPOTID), objbizet.Title, objbizet.Keywords, objbizet.Path, strVideoFile, objbizet.CLIENTNAME, Convert.ToInt32(objbizet.CLIENTID), objbizet.SUBCATEGORYNAME, Convert.ToInt32(objbizet.SUBCATEGORYID), Convert.ToDecimal(objbizet.PRICE), strThumbfile, objbizet.Description);
}
else
{
db2.AddMedia(Convert.ToInt32(objbizet.SPOTID), "Under Maintenance - " + objbizet.Title, objbizet.Keywords, objbizet.Path, strVideoFile, objbizet.CLIENTNAME, Convert.ToInt32(objbizet.CLIENTID), objbizet.SUBCATEGORYNAME, Convert.ToInt32(objbizet.SUBCATEGORYID), Convert.ToDecimal(objbizet.PRICE), strThumbfile, objbizet.Description);
}
}
}
//dispose
db.Dispose();
db2.Dispose();
}
}
}

Related

Sending a mail or invite through asp

I'm trying to send email or invite dynamically using asp page.
I used,
Oapp = new Outlook.Application();
But the problem is when executed, the page tries to open a new outlook application and sends a mail. I want the page to use the existing or open outlook application and send a mail.
Can anyone help me???
Microsoft does not currently recommend, and does not support, Automation of Microsoft Office applications from any unattended, non-interactive client application or component (including ASP, ASP.NET, DCOM, and NT Services), because Office may exhibit unstable behavior and/or deadlock when Office is run in this environment.
If you are building a solution that runs in a server-side context, you should try to use components that have been made safe for unattended execution. Or, you should try to find alternatives that allow at least part of the code to run client-side. If you use an Office application from a server-side solution, the application will lack many of the necessary capabilities to run successfully. Additionally, you will be taking risks with the stability of your overall solution. Read more about that in the Considerations for server-side Automation of Office article.
As a workaround you may consider using EWS or Outlook API, see EWS Managed API, EWS, and web services in Exchange for more information.
For sending emails use System.Net.* classes for sending emails from the server-side.
public static void CreateMessageWithAttachment(string server)
{
// Specify the file to be attached and sent.
// This example assumes that a file named Data.xls exists in the
// current working directory.
string file = "data.xls";
// Create a message and set up the recipients.
MailMessage message = new MailMessage(
"jane#contoso.com",
"ben#contoso.com",
"Quarterly data report.",
"See the attached spreadsheet.");
// Create the file attachment for this e-mail message.
Attachment data = new Attachment(file, MediaTypeNames.Application.Octet);
// Add time stamp information for the file.
ContentDisposition disposition = data.ContentDisposition;
disposition.CreationDate = System.IO.File.GetCreationTime(file);
disposition.ModificationDate = System.IO.File.GetLastWriteTime(file);
disposition.ReadDate = System.IO.File.GetLastAccessTime(file);
// Add the file attachment to this e-mail message.
message.Attachments.Add(data);
//Send the message.
SmtpClient client = new SmtpClient(server);
// Add credentials if the SMTP server requires them.
client.Credentials = CredentialCache.DefaultNetworkCredentials;
try
{
client.Send(message);
}
catch (Exception ex)
{
Console.WriteLine("Exception caught in CreateMessageWithAttachment(): {0}", ex.ToString() );
}
// Display the values in the ContentDisposition for the attachment.
ContentDisposition cd = data.ContentDisposition;
Console.WriteLine("Content disposition");
Console.WriteLine(cd.ToString());
Console.WriteLine("File {0}", cd.FileName);
Console.WriteLine("Size {0}", cd.Size);
Console.WriteLine("Creation {0}", cd.CreationDate);
Console.WriteLine("Modification {0}", cd.ModificationDate);
Console.WriteLine("Read {0}", cd.ReadDate);
Console.WriteLine("Inline {0}", cd.Inline);
Console.WriteLine("Parameters: {0}", cd.Parameters.Count);
foreach (DictionaryEntry d in cd.Parameters)
{
Console.WriteLine("{0} = {1}", d.Key, d.Value);
}
data.Dispose();
}

Using WebClient to get a intranet files

In our I have company intranet a server, that is responsible for storing files. Initially, the server had to operate only in an intranet environment, but now there is a need to share files with external web applications. Making this server accessible from the internet is not an option.
I want to create a ASP.NET MVC solution that uses the WebClient to get these files from the intranet server and send back them to the user through FileResult of the external app. This client would be provided with custom domain user credentials. So far I have tried to create a CredentialCache class, set correct credentials and append it to WebClients Credentials property like in the following code:
public ActionResult Download(int id, string fileName)
{
var fileService = new FilesService();
var documentUrl = fileService.GetUrlFileByFileId(id);
string filePath = "http://my.intranet.com/" + documentUrl;
var fileNameFromUrl = filePath.Substring(filePath.LastIndexOf("\\") + 1);
byte[] filedata;
CredentialCache cc = new CredentialCache();
cc.Add(new Uri("http://my.intranet.com/"),
"ntlm",
new NetworkCredential("myUserName", "myPassword", "myDomain"));
using (var client = new WebClient())
{
client.Credentials = cc;
filedata = client.DownloadData(filePath);
}
string contentType = MimeMapping.GetMimeMapping(filePath);
var cd = new ContentDisposition
{
FileName = fileName,
Inline = false
};
Response.AppendHeader("Content-Disposition", cd.ToString());
return File(filedata, contentType);
}
According to the question posted in Domain credentials for a WebClient class don't work it should work, but it’s not. It’s running only if I run the problem on localhost, but when I publish my solution on a test server, it return 401 error. My question is did how to get this working? And is it possible to download files through this method?
UPDATE--- I've published my test app on another server and it started to working. Now the test app is on another server than the server That stores files. Any ideas why it's not working when both are on the same machine?
401 error is unauthorized, so perhaps the issue is related to permissions. Are you sure the user account you are using to login to that folder has the proper access?
Ok, I found the solution on this site: https://blogs.msdn.microsoft.com/distributedservices/2009/11/10/wcf-calling-wcf-service-hosted-in-iis-on-the-same-machine-as-client-throws-authentication-error/
The solution was to add an registry entry and add my web apps to this entry to allow back connections.

How to specify credentials from a Java Web Service in PTC Windchill PDMLink

I am currently investigating the possibility of using a Java Web Service (as described by the Info*Engine documentation of Windchill) in order to retrieve information regarding parts. I am using Windchill version 10.1.
I have successfully deployed a web service, which I consume in a .Net application. Calls which do not try to access Windchill information complete successfully. However, when trying to retrieve part information, I get a wt.method.AuthenticationException.
Here is the code that runs within the webService (The web service method simply calls this method)
public static String GetOnePart(String partNumber) throws WTException
{
WTPart part=null;
RemoteMethodServer server = RemoteMethodServer.getDefault();
server.setUserName("theUsername");
server.setPassword("thePassword");
try {
QuerySpec qspec= new QuerySpec(WTPart.class);
qspec.appendWhere(new SearchCondition(WTPart.class,WTPart.NUMBER,SearchCondition.LIKE,partNumber),new int[]{0,1});
// This fails.
QueryResult qr=PersistenceHelper.manager.find((StatementSpec)qspec);
while(qr.hasMoreElements())
{
part=(WTPart) qr.nextElement();
partName = part.getName();
}
} catch (AuthenticationException e) {
// Exception caught here.
partName = e.toString();
}
return partName;
}
This code works in a command line application deployed on the server, but fails with a wt.method.AuthenticationException when performed from within the web service. I feel it fails because the use of RemoteMethodServer is not what I should be doing since the web service is within the MethodServer.
Anyhow, if anyone knows how to do this, it would be awesome.
A bonus question would be how to log from within the web service, and how to configure this logging.
Thank you.
You don't need to authenticate on the server side with this code
RemoteMethodServer server = RemoteMethodServer.getDefault();
server.setUserName("theUsername");
server.setPassword("thePassword");
If you have followed the documentation (windchill help center), your web service should be something annotated with #WebServices and #WebMethod(operationName="getOnePart") and inherit com.ptc.jws.servlet.JaxWsService
Also you have to take care to the policy used during deployment.
The default ant script is configured with
security.policy=userNameAuthSymmetricKeys
So you need to manage it when you consume your ws with .Net.
For logging events, you just need to call the log4j logger instantiated by default with $log.debug("Hello")
You can't pre-authenticate server side.
You can write the auth into your client tho. Not sure what the .Net equivilent is, but this works for Java clients:
private static final String USERNAME = "admin";
private static final String PASSWORD = "password";
static {
java.net.Authenticator.setDefault(new java.net.Authenticator() {
#Override
protected java.net.PasswordAuthentication getPasswordAuthentication() {
return new java.net.PasswordAuthentication(USERNAME, PASSWORD.toCharArray());
}
});
}

Execute a server side program asynchronously with an asp.net mvc4 app

is it possible to execute a server side program and get the output asynchronously.
i have this code that doing the job but synchronously:
suppose a c# program "program.exe" like this :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace testconsole
{
class Program
{
static void Main(string[] args)
{
for (int k = 0; k < 10; k++ )Console.WriteLine(k);
}
}
}
some view in the asp.net app like this :
<script >
function go()
{
var options = {
url: '/excute',
type: 'GET',
dataType: 'json'
}
//make call
$.ajax(options)
.then(function (data) {
console.log(data);
});
}
</script>
<input type="submit" onclick="go();" value="Go">
and the excute controller looks like this :
namespace myApp.Controllers
{
public class ExecuteController : Controller
{
//
// GET: /Execute
[HttpGet]
public JsonResult Index()
{
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "program.exe";
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
return Json(new { op = output }, JsonRequestBehavior.AllowGet);
}
}
}
All this is working fine, But ... from the client have to wait till the end of the program to display its outputs, is there any way to get those outputs as soon as they r created?
im sur i need to make some changes in the controller to make it possible, but how ???
Asp.Net MVC has the concept of an Async Controller that is suited to perform long-running tasks. It will help you by not locking a thread while you wait for out program to execute.
But to do what you are after I think you need to create you own Http Handler (probaby by implementing the IHttpHandler interface) that wraps the process and returns the results incrementally. This will not be trivial to do, but it should be possible.
A third viable alternative might be to use SignalR. That would be a fun project, but would still require much work I think.
The problem is primarily with communication between the IIS host process and your external process. You would need to facilitate some sort channel of communication to send "progress" events from the console application into the ASP.NET application.
A WCF client sending information via named pipes to a service hosted in the ASP.NET application would enable you to send messages into the application. You would host the service when the request is made and dynamically generate the name of pipe as a way to correlate to the initial request.
Once you get the updates in the application, you could then use something like SignalR to allow you to push the information back up the client.
Im back finally with an answer (not perfect i suppose). I used SignalR to get this done.
i created a messenger program (with c#) that will be the bridge between an asp.net mvc4 application and any console program that displays outputs.
the messenger will execute the program , then redirect his outputs to be send trough SignalR to the client.
if you are interested i've created a repo at github for this ,check this code here. I hope it will help someone one day.
i will be happy to talk about this code with you.

asp.net web api: accessing uploaded file stream

I have an asp.net web api application which is acting as a Relay to a wcf web service. In certain scenarios I want to upload large files. The methods in the wcf service accept files as stream.
I do not want to save the files on my intermediate server I want to access the stream of the uploaded file and provide it to the wcf method so that the data is directly streamed to the wcf service.
Here is similar scenario when client is downloading the file
using (IProductsChannel channel = ChannelFactory.CreateChannel())
{
result.Content = new StreamContent(channel.GetFile());
result.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain");
return result;
}
Here is at least one way of doing it. using the HTTPContext the only problem with this one is that it is not good for unit testing so we have to abstract it out in the final solution.
var file = HttpContext.Current.Request.Files[0];
var result = new HttpResponseMessage(HttpStatusCode.OK);
using (IProductsChannel channel = ChannelFactory.CreateChannel())
{
channel.SaveFile(file.InputStream);
}
return new HttpResponseMessage(HttpStatusCode.Created);
}

Resources