Telerik asp.net MVC Fileupload control - c#

I am using Telerik asp.net MVC 3 file control in my Razor view (Catalog/Product View) like this:
#(Html.Telerik().Upload()
.Name("orderImageAtachment")
.Async(async => async.Save("Save", "Catalog").AutoUpload(true))
.ClientEvents(events => events
.OnSuccess("ItemImageOnSuccess")
.OnError("ItemImageOnError")
)
)
I have created an ActionResult like this:
public ActionResult Save(IEnumerable<HttpPostedFileBase> orderImageAtachment, string CompID)
{
// The Name of the Upload component is "attachments"
foreach (var file in orderImageAtachment)
{
// Some browsers send file names with full path. This needs to be stripped.
var fileName = Path.GetFileName(file.FileName);
var physicalPath = Path.Combine(Server.MapPath("~/Content/Docs"), fileName);
// The files are not actually saved in this demo
file.SaveAs(physicalPath);
}
// Return an empty string to signify success
return Content("");
}
and client side functions like this:
function onSuccess(e) {
// Array with information about the uploaded files
var files = e.files;
if (e.operation == "upload") {
alert("Successfully uploaded " + files.length + " files");
}
}
function onError(e) {
alert('Error in file upload');
// Array with information about the uploaded files
var files = e.files;
if (e.operation == "upload") {
alert("Failed to uploaded " + files.length + " files");
}
// Suppress the default error message
e.preventDefault();
}
I get select button which opens browse window. But clicking it does nothing.... I am not sure whats wrong. Do I need to add something in web.config? Please suggest.

I'm a little confused at which point its not working, but I'm assuming its not hitting the action in your controller. I'd make sure you are trying a fairly small file, the default limit is 4mb.
Also it looks like the signature of your Save Action does not match the route you are giving it in the upload's async.Save(...). I'm not sure it will matter since its a string, but you might try removing the Save actions's CompID parameter (doesn't look like its used in the snippet at least).
I'd try using fiddler or the developer tools in whichever browser you are using to see if u are getting a 404 error by chance.

Related

Not getting the Uploaded filepath in asp.net

I want to save file to a specific location with some folder creation based on my requirement. So I wrote the below code.
public string CreateFilePath(string addedFolderName)
{
string folderPath = ConfigurationManager.AppSettings["DocDirectory"].ToString();
string FileUplPath = folderPath + "\\" + addedFolderName + "\\";
if (!Directory.Exists(FileUplPath))
{
Directory.CreateDirectory(FileUplPath);
}
flUploadDocs.SaveAs(FileUplPath + Path.GetFileName(flUploadDocs.FileName));
return folderPath;
}
But I am unable to get the filepath here. I am getting it as null
getting null at
Path.GetFileName(flUploadDocs.FileName)
<asp:FileUpload ID="flUploadDocs" runat="server" />
Please suggest what is wrong here.
Path.GetFileName() returns the file name and extension of the specified path string
if im correct this only fills in the file name and not the directory + name.
Path.GetFileName(flUploadDocs.FileName)
possible solution
Path.GetFileName(FileUplPath+flUploadDocs.FileName)
eventough im confused why you try to retrieve the path again after just having saved it?
The issue is that the webservice does not have the fileupload data. Here is the full code from our extended conversation:
[WebMethod]
public static string InsertUpdateMWSiteData(MWInsertUpdateFields MWInsertUpdateFields)
{
string strInsertUpdateMWInfo = "";
try
{
Dashboard dshb = new Dashboard();
dshb.CreateFilePath(MWInsertUpdateFields.SapID + "_" + MWInsertUpdateFields.CandidateID);
strInsertUpdateMWInfo = CommonDB.InsertUpdateMWSiteInfo(MWInsertUpdateFields);
}
catch (Exception)
{
throw;
}
return strInsertUpdateMWInfo;
}
public string CreateFilePath(string addedFolderName)
{
string folderPath = ConfigurationManager.AppSettings["DocDirectory"].ToString();
string FileUplPath = folderPath + "\\" + addedFolderName + "\\";
if (!Directory.Exists(FileUplPath))
{
Directory.CreateDirectory(FileUplPath);
}
if (flUploadDoc.HasFile == true)
{
string strFilename = Path.GetFileName(flUploadDoc.FileName);
flUploadDoc.SaveAs(FileUplPath + Path.GetFileName(flUploadDoc.PostedFile.FileName));
}
return folderPath;
}
The problem is that after uploading a file, a request is sent to a webmethod which is being hosted in another instance of the program. This Webmethod checks its own instance for the fileupload control and data, and doesn't find it because it is in a different instance. This is why your fileupload control is returning null even on a sanity check of .HasFile().
One solution is to pass the data to the Webservice. You could for example pass the data to your webmethod as a byte[], and then on the webservice side reconvert it back into its original file type. After completing this process, save the file to your local filesystem. To do this you may need to pass the extension type and file name.
You may also want to add some validation to limit the file types accepted to only the most common file types like images, .doc, .excel, and whatever you have the library to support the conversion of.
If you want to save files directly to your filesystem using the upload control, you can do so but you will have to exclude the webservice step.
Please also see the discussion in chat for details.

.NET/C# How to render static HTML from a separate folder with relative referenced content

I'm developing a custom CMS. I have content per ResearchArticle stored in Azure blobs. The content consists of an index.html file with any related images, pdf's etc. the index.html page uses relative local references as in:
<img src="chuck-norris-1.jpg" />
This is so our designer can make articles with related content and put it all in one folder to be sent to an Azure blob container. Each web server then downloads the content into a local ResearchArticle content folder structure as in:
ResearchArticleBodyLocal\abc
So, now I have to display this content when someone views the article. I was reading the index.html into a string and using #Html.raw(). Problem is, from the view, the relative references aren't working because the view, obviously, is in a different location than the content.
but #1 the relative references are off, and #2 for some reason it's running the action method twice as if it has a jQuery problem, but I'm not using any JQuery here...
Here's what I'm trying:
controller method-
ravm.ArticleBodyIndexHtmlPath = System.IO.File.ReadAllText(Server.MapPath(ConfigurationManager.AppSettings["ResearchArticleBodyRelativeLocalDirectory"] + researchArticle.BodyRelativeLocalPath + "/index.html"));
View -
#(Html.Raw(Model.ArticleBodyIndexHtmlPath))
I've also tried this solution but the relative reference thing is still a problem... Anyone have a vision of how to solve this without having the designer put the intended directory structure into the content references?
You could perhaps put the directory structure there using a bit of string replacement/regex? I do that within my own templating system so that the designer can do src="chuck-norris.jpg" and I replace it depending on the site being hit with src="/othersite-image-dir/chuck-norris.jpg" automatically. That way my designer doesn't have to remember directories.
The other way around it is to have a specific directory structure for your objects, i.e
images
js
css
That way the designer can go src="/js/my-chuck-norris.js" and always hit the file regardless of which site it's in
Yes, I wound up doing this:
private List<string> GetFilePathsAndUpdateIndexHtml(string bodyFolderChoices, string containerName)
{
// get path to each item
var filePaths =
Directory.GetFiles(
Server.MapPath(ConfigurationManager.AppSettings["ResearchArticleFTPUploadRoot"] + "/" +
bodyFolderChoices));
// get root from web.config
var azureRootUrl = ConfigurationManager.AppSettings["AzureBlobRootUrl"] + containerName + "/";
// find index.html and replace relative references
foreach (var s in filePaths)
{
if (s.Contains("index.html"))
{
var doc = new HtmlDocument();
doc.LoadHtml(System.IO.File.ReadAllText(s));
HtmlNodeCollection links = doc.DocumentNode.SelectNodes("//*[#background or #lowsrc or #src or #href]");
if (links == null)
continue;
foreach (HtmlNode link in links)
{
// references to outside URLs this will break unless we check for 'http' and leave alone
if (link.Attributes["background"] != null && !link.Attributes["background"].Value.Contains("http"))
link.Attributes["background"].Value = azureRootUrl + link.Attributes["background"].Value;
if (link.Attributes["href"] != null && !link.Attributes["href"].Value.Contains("http"))
link.Attributes["href"].Value = azureRootUrl + link.Attributes["href"].Value;
if (link.Attributes["lowsrc"] != null && !link.Attributes["lowsrc"].Value.Contains("http"))
link.Attributes["lowsrc"].Value = azureRootUrl + link.Attributes["lowsrc"].Value;
if (link.Attributes["src"] != null && !link.Attributes["src"].Value.Contains("http"))
link.Attributes["src"].Value = azureRootUrl + link.Attributes["src"].Value;
}
doc.Save(s);
}
}
return filePaths.ToList();
}

open window explorer folder from my results c#

iv made a web forum, as i have lots of folders on my local drive i can now search for any folders i want on webpage.
Now am looking to add a link to the results of the search so it takes me directly to the folder.
My code in c#:
protected void List_Dirs(string searchStr = null)
{
try
{
MainContentLocal.InnerHtml = "";
string[] directoryList = System.IO.Directory.GetDirectories("\\\\myfiles\\Web");
int x = 0;
foreach (string directory in directoryList)
{
if (searchStr != null && searchStr.Length > 1)
{
UserInfo.Text = "Your Search for : <strong>" + SearchPhrase.Text + "</strong> returns ";
if(directoryP.ToLower().Contains(searchStr.ToLower()))
{
MainContentLocal.InnerHtml += directoryP + "<br />";
x++;
}
}
else
{
MainContentLocal.InnerHtml += directoryP + "<br />";
}
if (searchStr != null && searchStr.Length > 1)
{
UserInfo.Text += "<strong>" + x.ToString() + "</strong> results";
UserInfo.CssClass = "userInfo";
}
}
catch(Exception DirectoryListExp)
{
MainContentLocal.InnerHtml = DirectoryListExp.Message;
}
}
When i enter something is search i will get a list of folders like:
Your Search for : project returns 2 results
job234 project234 Awards
job323 project game
now is there any way for me to click the result so i can open a window explore on the webpage
Thanks
You can create links like project234.
string folder = "\\\\myfiles\\Web";
if (string.IsNullOrWhiteSpace(Request["folder"])) {
// Folder clicked
folder = string.Format("{0}{1}", folder, Request["folder"]);
Process.Start(folder);
}
string[] directoryList = System.IO.Directory.GetDirectories(folder);
Then it will open it on the server. So if it really is local, than it will work. If there is no security problem. But I'm not sure. You can also use file:// links (as Ryan Mrachek notes), but browsers are not happy to let you open them.
If your result is a file, you can open that file programmatically through the Process class by invoking Process.Start("C:\\MyResults.txt"). This will open the results in the default text editor. In the same way, you can also open a web page by inserting passing a Url to Process.Start. I hope this is what wanted.
our file urls are malformed. It should be:
file:///c:/folder/
Please refer to The Bizarre and Unhappy Story of File URLs.
This works for me:
link
When you click Link, a new Windows Explorer window is opened to the specified location. But as you point out, this only works from a file:// URL to begin with.
A detailed explanation of what is going on can be found here. Basically this behavior by design for IE since IE6 SP1/SP2 and the only way you can change it is by explicitly disabling certain security policies using registry settings on the local machine.
So if you're an IT admin and you want to deploy this for your internal corporate LAN, this might be possible (though inadvisable). If you're doing this on some generic, public-facing website, it seems impossible.

Uploading a file to Sitecore keeping the extension in the DisplayName

As the title says, I'm trying to upload a file to somewhere in my Sitecore tree from the web and I want to keep the file's extension in the DisplayName of the item.
I tried using MediaCreator, but it requires a specific filepath which I do not know when I let people select a file using asp:FileUpload. So that's no good.
I'm now using the asp:FileUpload in combination with a pipeline. When I use Sitecore.Pipelines.Upload.Save from Sitecore.Kernel it works except it removes the extension of the file from the DisplayName. So I created a custom pipeline method that looks like this:
using System;
using System.IO;
using Sitecore.Diagnostics;
using Sitecore.IO;
namespace Sitecore.Pipelines.Upload
{
public class CustomSave
{
public void Process(UploadArgs args)
{
foreach (string key in args.Files)
{
var file = args.Files[key];
if (file != null && file.FileName.Length > 0 && file.ContentLength > 0)
{
var filename = FileUtil.MakePath(args.Folder, Path.GetFileName(file.FileName), '/');
try
{
if (!args.Overwrite)
{
filename = FileUtil.GetUniqueFilename(filename);
}
file.SaveAs(filename);
EventDispatcher.DispatchTrace("File has been uploaded: " + filename);
}
catch (Exception ex)
{
Log.Error("Could not save posted file: " + filename, ex, this);
}
}
}
}
}
}
The problem I now face is that it's trying to save to my C:\ disk instead of the Sitecore database.
Any suggestions on how to write to the correct destination?
The end goal, as explained, is to use the client friendly asp:FileUpload to select a file and upload it to a specific path in Sitecore retaining the file's extension in its DisplayName. If you have another way to do that I'd like to hear about it too.
There is a setting that appends file extension to the item name
"Media.IncludeExtensionsInItemNames". If you can live with that, just turn it on.
Otherwise, I'd add a custom processor into "uiUpload" after "Save" one. At that moment you would already have a list of created media items from "args.UploadedItems". You can do your simple manipulations with items in there.

In ASP.NET, What could cause image manipulation to fail when using Fx or chrome, but succeed when using IE?

I am in a rather unusual pickle. I am modifying an image uploader and I thought I had it working. It needed to:
take a file from the client and upload it to server.
If file is an image, perform resizing operations on it.
If file is an image, create a thumbnail.
What I have works great when uploading images with Internet Explorer 8. But, when I upload images using Chrome, or Firefox3.+, the image gets uploaded but steps 2 and 3 are not performed. I don't get any server errors or anything. As 2 and 3 are steps that are performed on the server I have no idea how a change in browser could effect them.
I'm not sure if it has anything to do with my checking for whether the file is an image or not. But, for the sake of being thorough, here's the code I use:
try
{
string Filename = FileSystemUtilities.CleanupFilename(Path.GetFileName(hpf.FileName));
Filename = hpf.FileName;
string FileToSave = DestDir + Path.DirectorySeparatorChar + Path.GetFileName(Filename);
hpf.SaveAs(FileToSave);
bool IsImageFileType = ImageUtilities.IsImage(Filename, imageExtensions);
// below does not seem to execute when using non ie browser
// everything is smooth sailing when using ie.
if (IsImageFileType)
{
ImageUtilities.ResizeImageIfNecessary(FileToSave, mainMaxWidth, mainMaxHeight);
ImageUtilities.CreateThumbnail(FileToSave, thumbMaxWidth, thumbMaxHeight);
}
ValidOperation++;
sb.AppendFormat("{0} uploaded successfully<br/>", Filename);
}
Any thoughts? Why would server side code behave differently based on browser?
Edit: ImageUtilities.IsImage()
public static bool IsImage(string file, string[] imageExtensions)
{
file = Path.GetFullPath(file);
if (File.Exists(file))
{
string CurrentFileExtension = Path.GetExtension(file);
return imageExtensions.Count(x => x == CurrentFileExtension) > 0 ? true : false;
}
else
{
return false; //file doesn't exist
}
}
This difference would be caused by a difference in the filename sent by the browsers.
For example, some browsers include the full path.
Your ImageUtilities.IsImage function can't handle the filename sent by non-IE browsers.
EDIT: Your function is very wrong.
Change it to
return imageExtensions.Contains(Path.GetExtension(file),
StringComparer.OrdinalIgnoreCase);

Categories