PDA

View Full Version : File Upload Dialog



davidhoyt
Oct 09, 2008, 3:55 AM
<P align=left>Please see this post for the latest version: http://forums.ext.net/showthread.php?postid=8229.aspx


I know there's been talk about this in the forums before, but has anyone created the file upload dialog UX? The one here: http://www.max-bazhenov.com/dev/upload-dialog-2.0/index.php

I've been attempting to do it, but as this is my first ExtJS experience, it's slow going and I haven't made much progress. I know server controls very well (having authored multiple ones myself - include richtextboxes), but I'm still familiarizing myself w/ the ExtJS + Coolite APIs.

I have it so I can drop in the control into the designer and it appears, but at runtime IE gives me a javascript error "Invalid source HTML for this operation." On Firefox 3.0, it appears, but the dialog is squished down. When you resize it, it takes on its correct min width/height.

I figure this is probably a version issue since the javascript I pulled from that site is for 2.0 and ExtJS is on 2.2. However, I don't know where to begin to address the issue.

Can anyone help? Here's the code I have so far:



using System;
using System.Web.UI;
using System.Drawing;
using System.ComponentModel;
using Coolite.Ext.Web;

[assembly: WebResource("ServerControls.Resources.Scripts.Ext.ux.UploadDial og.packed.js", "text/javascript")]
[assembly: WebResource("ServerControls.Resources.Scripts.Ext.ux.UploadDial og.js", "text/javascript")]

namespace ServerControls {

[ToolboxData("<{0}:FileUploadDialog runat=\"server\" Title=\"Upload Files\" Collapsible=\"false\" Icon=\"None\" />")]
[ToolboxBitmap(typeof(FileUploadDialog), "Resources.ToolboxIcons.window.bmp")]
[Designer(typeof(FileUploadDialogDesigner))]
[Description("Specialized dialog for uploading files.")]
[InstanceOf(ClassName = "Ext.ux.UploadDialog.Dialog")]
[ClientScript(
Type = typeof(FileUploadDialog),
WebResource = "ServerControls.Resources.Scripts.Ext.ux.UploadDial og.packed.js",
WebResourceDebug = "ServerControls.Resources.Scripts.Ext.ux.UploadDial og.js"
)]
public class FileUploadDialog : Window {
protected override void OnBeforeClientInit(Observable sender) {
base.OnBeforeClientInit(sender);
}
protected override void OnAfterClientInit(Observable sender) {
base.OnAfterClientInit(sender);
}
}
}

Here's the designer code:



using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using Coolite.Ext.Web;

namespace ServerControls {
internal class FileUploadDialogDesigner : ExtWebControlDesigner {
public override bool AllowResize {
get {
return false;
}
}

public override string GetDesignTimeHtml() {
if (((FileUploadDialog)this.Control).Hidden) {
return string.Empty;
}
return base.CreatePlaceHolderDesignTimeHtml();
}

private DesignerActionListCollection actionLists;
public override DesignerActionListCollection ActionLists {
get {
if (actionLists == null) {
actionLists = new DesignerActionListCollection();
actionLists.Add(new FileUploadDialogActionList(this.Component));
}
return actionLists;
}
}
}

internal class FileUploadDialogActionList : WindowActionList {
public FileUploadDialogActionList(IComponent component) : base(component) {
}

public override DesignerActionItemCollection GetSortedActionItems() {
return base.GetSortedActionItems();
}
}
}

Sample web content page:



<%@ Page Title="File Upload Dialog" Language="C#" MasterPageFile="~/site.master" AutoEventWireup="true" CodeBehind="fileUploadDialog.aspx.cs" Inherits="Sandbox.fileUploadDialog" %>
<%@ Register Assembly="Coolite.Ext.Web" Namespace="Coolite.Ext.Web" TagPrefix="ext" %>
<%@ Register Assembly="ServerControls" Namespace="ServerControls" TagPrefix="ux" %>

<asp:Content ID="content" ContentPlaceHolderID="content" runat="server">

<ext:ScriptManager ID="ScriptManager" runat="server" />
<br />

<ux:FileUploadDialog ID="FileUploadDialog1" runat="server" Collapsible="True" Icon="Cart" Title="Upload Files" Draggable="true" Floating="true" Maximizable="True" Modal="True" ShowOnLoad="False" />

<ext:Button ID="Button1" runat="server" Icon="ReportAdd" Text="Upload Files">
<Listeners>
<Click Handler="#{FileUploadDialog1}.show()" />
</Listeners>
</ext:Button>

</asp:Content>

Thanks!

geoffrey.mcgill
Oct 09, 2008, 9:15 AM
Hi davidhoyt,

This FileUploadDialog UX control is a monster one to bite off. Props to you taking this one on.

I took a quick look at the files within the .zip download and there is a .css file included which I suspect is required. That might help solve the FF3 rendering issue you mentioned.

You can add the .css file as an embedded resource to your project then add the [ClientStyle] attribute to FileUploadDialog class, just like the [ClientScript] attribute. Please ensure you set all the resource files (.js, .css, images) as Embedded Resources from within Visual Studio.

I'm not sure about the IE JavaScript error. If you view the page in FireFox with FireBug are there any JavaScript errors/exceptions thrown? Actually... this sounds like maybe a problem with an extra (or missing) comma within the packed version of the .js files. Confirm if the js error is being thrown with the debug version of the .js file.

Some of the images might also be required, so you should add them as embedded resources and add the [assembly: WebResource()] attributes to FileUploadDialog.cs, just like you have done for the .js files.

The other trick with having embedded resource images is that you have to edit the .css file and create an "-embedded" version, where you replace all the "url(../path/here.gif)" references with WebResource assembly paths, url("<%=WebResource("assmebly.path.here")%>"). See the Coolite Toolkit "ext-all-embedded.css" file for reference.

I hope this helps solve some of the problems.

davidhoyt
Oct 09, 2008, 4:52 PM
Honestly, I was hoping it would be quite easy. I'm not sure about the design-time experience, but I would hope wiring everything else up would be easy.

Using the Coolite API, how do I attach a file upload event?

My server control days were before AJAX - and I figure you guys already have something in place to do this easily.

It looks like all I really need to do is to be able to set the upload URL - which I'm hoping I can set to be the page the control is hosted on. And then hopefully intercept the upload.

How are you guys approaching it for the new file upload control?

And, by the by, please do not make it cache the entire contents of the file in memory like the current ASP.NET file upload control does. Hopefully you can create a stream or something of the sort.

davidhoyt
Oct 10, 2008, 5:39 AM
Turns out some of my errors were stylesheet issues in the CSS we had defined for the site. The CSS and associated images (as embedded resources) are all downloading just fine from the assembly. I still need some help, though...

1. How do I include something in the clientconfig without having to decorate a property with the ClientConfig attribute? (e.g. I have a config option that I want to set, but don't want it publically accessible. Do I just make the property internal/protected/private?)

2. What are the proper design-time features for this? Should it look like a dialog at design time or what? Currently I don't do much for it.

3. I'm still very inexperienced with ExtJS. When you click on the "Add" button and select a file, nothing happens. If you create the object outside of coolite using javascript, everything functions as intended. What could be the difference?

4. The server control version's dialog doesn't allow it to be dragged around like the normal straight javascript version does.

5. I still get the IE error and haven't been able to figure out what's going on. I'm using the debug version and still nothing.

I could sure use some help. Mainly w/ #s 3-5 there. I've attached my source as an example. I welcome anyone's suggestions/aid.

davidhoyt
Oct 10, 2008, 9:49 PM
Regarding #4 above - I stripped it down to nothing more than inheriting from Ext.Window and it still won't behave correctly on the page load.

If I create it via javascript at the end of the HTML, it works and behaves correctly.

What's going on?

Thanks for any help you can provide! (c:

davidhoyt
Oct 10, 2008, 10:01 PM
I could really use some help. Wasn't help offered in http://forums.ext.net/showthread.php?postid=1455.aspx? (c:

Sorry to bug - I just don't know anyone else that can help with this. No one I know has ExtJS/Coolite API experience.

I would be happy to add this to the UX project. I already attached my code in a previous post.

Again, thanks for any/all help received! (c:

mindcore1
Oct 14, 2008, 11:03 AM
I was looking at #4 using the FireFox Web Developer Toolkit and see some restrictive CSS called .ext-strict that seems to prevent the window from floating down. I wasn't able to get any further because I ran out of time.

mindcore1
Oct 15, 2008, 1:08 AM
Ok, I've researched your problems some more and found a difference between the Coolite version and the raw JavaScript version. Near the end of the rendered output of the JavaScript version, the following line occurs...



<form style="position: absolute; left: -100px; top: -100px; width: 100px; height: 100px;" action="/upload.ashx" method="post"/>


This line isn't present in your Coolite Version because this code gets rendered to the page's 'aspnetForm' form element. Since it gets rendered to this element during the initial page load, the form element inherits ext-strict css from its parent element which has a height that resricts the control from being moved down.

Unfortunately, traditional ASP.NET only has one form tag for the whole page. So you may have to modify the raw JavaScript for this Control to function properly in ASP.NET. Also, this may be what's causing your #5 issue.

I hope this helps you out.

-mc

davidhoyt
Oct 16, 2008, 10:34 AM
Okay, here's an almost functioning control. It needs some major design-time help, though. I'm a bit rusty in that area. I'd love it if someone had the time to do that. There are some instances where if you try to work with it in the designer it crashes VS. *doh* But if you always work in HTML (source), there's never a problem.

I'm still working on a few Firefox bugs, but I thought I'd submit what I have so people can test it out and see if they like it.

The file upload uses an HttpModule to catch the post and then allows you to stream it as it comes in instead of buffering it in memory. To process the file, you set the ProcessorType property on the control. Check out the Test/Default.aspx.cs code for an example of how to serialize a file stream to disk. The data is passed in as a stream so you can do anything you'd like with it (e.g. stream to a database).

I had to make one change to the source that I've submitted back to the author and hopefully he'll include it in the next version.

To get around the errors I had discovered before, I just used Page.ClientScript(...) to create the dialog at the end of the page. That seemed to work. Go figure...

Anyway - enjoy!

davidhoyt
Oct 16, 2008, 10:38 AM
Oh and I purposely made the HttpModule extensible in case anyone needs to customize it for their needs.

And I apologize for the missing references - the forum imposes a file upload limit and so I had to take it out so it would fit.

Zarzand
Oct 23, 2008, 5:13 PM
Where do we specify the path for the file to be uploaded to.

Thanks

davidhoyt
Oct 23, 2008, 5:48 PM
You have 2 options. It'll post back to the same page if you don't specify PostURL (think of it as setting a form's action attribute). If you use the provided HTTPModule (see the web.config), you can specify ProcessorType and provide a class that implements the IFileUploadProcessor interface or extends AbstractFileUploadProcessor. See the Default.aspx.cs file for more details.

Using the HTTPModule is preferred because it allows you to intercept the request and not buffer the file in memory before storing it. Just add the following to the system.web/httpModules/ node:

<add name="FileUploadModule" type="ServerControls.FileUploadModule, ServerControls"/>

methode
Nov 18, 2008, 8:33 AM
Hi davidhoyt,

I saw the code, great work!
The code works fine, but I have in my code that every Session variable is null.

context.Session is always null, I really don't understand why?

While context.Request.QueryString["myVariable"] works fine.

Have you got an idea?




private class FileProcessor : AbstractFileUploadProcessor
{
protected override void processUpload(
HttpContext context,
IPost post,
System.IO.Stream stream,
byte[] buffer,
int bufferSize,
System.Text.Encoding encoding)
{
//Saves files to the current project's directory. You should probably do something more intelligent here.

int read = 0;
byte[] _documentbyte = new byte[bufferSize];
using (FileStream fs = new FileStream(context.Server.MapPath("~/" + post.FileName), FileMode.Create))
{
while ((read = stream.Read(buffer, 0, bufferSize)) >= 0)
fs.Write(buffer, 0, read);
fs.Close();
}

// all fine up to here

if (context.Session["mySessionName"] == null) return;

context.Session["mySessionName"] throws a NullReferenceException !

}
}




Thanx a lot

Matteo

davidhoyt
Nov 19, 2008, 4:43 PM
Yeah, I think I know exactly why. That class is instantiated and run in an HttpModule before the session information is loaded on a postback. I didn't think about sessions because our app requires sessionless connections.


I do have a couple of fixes I've been meaning to upload -- but until the session issue has been fixed, you can always use .AdditionalPostParameters() and pass in whatever you might need.


We use it to pass in the user's ID so we know who to associate the file with.


The reason I wrote the HTTP module was to get at the file being uploaded before it was cached in memory. I'll look into it.


I could still really use some help with the design-time portion of it.

methode
Nov 20, 2008, 3:37 AM
Hi davidhoyt,

thanx a lot for reply, ok I see.

Anyway I solved my problem and adopted the control in my web app and works fine.

Thanx

Matteo

euclidez
Dec 10, 2008, 10:14 PM
Hi David. Great job with this control. I had upload your solution on Godaddy shared hosting plan and had give folder permission (read/write) and setup virtual directory but I cannot do it works. The error tells me Upload Error. Can you have an idea of what is going on here? As I said I had upload the solution the only thing had change is:


using (FileStream fs = new FileStream(context.Server.MapPath("~/Upload/") + post.FileName, FileMode.Create)) {

Only a folder call Upload. The local version runs great and it's not a permission problem, I had test with the traditional asp.net FileUpload control and works well.

Any idea?

Thanks a lot !!!

davidhoyt
Dec 11, 2008, 2:56 AM
It could be a trust issue - it does use reflection. I don't have much experience in the shared hosting arena and running websites in partial trust environments. I usually have full control of the site and therefore never any permissions problems.

I'm hoping there's someone out there who could lend a hand with this problem?

I suppose debugging on the server would be difficult - but you could add a bunch of debug statements and output to a file to see if your handler is being called. You could ad-hoc your way into finding out where the code is dying. Once you find that, I might be able to be of more assistance.

In summary, insert debug statements throughout the code until you're able to pinpoint where it's dying. Then let me know the class, method name, and line where it's failing along with any pertinent information.

geoffrey.mcgill
Dec 11, 2008, 5:46 AM
Hi euclidez,

You should be able to determine if the problem is trust related by adding the following <trust> node to your web.config file and testing locally. Your app *should* fail locally under the same conditions.

Example


<system.web>
<trust level="Medium"/>
</system.web>


As a general rule, I almost always develop under "Medium" trust... especially if the app/site will eventually be hosted on a shared server. If for no other reason than to uncover potential permission issues early on in the development.

Not saying this upload thing is 100% a permission issue, but that would be my first guess as well.

methode
Jan 15, 2009, 12:33 PM
Hi all,

I have a problem with AdditionalParameters.
After I save my business object in AjaxEvent, how can I pass the new object ID to the FileUploadDialog parameters?

Steps:

- save business object
- retrieve new object id
- open file dialog and upload file + new object ID

Can you provide a simplified way of passing additional params?

Thanx a lot

Matteo

mindcore1
Jan 15, 2009, 2:56 PM
Just a suggestion,


Depending on what you are trying to accomplish, you may want to change your logic order to

- open file dialog and upload file (process will store to path, or database depending on your requirements)

- save business object with uploaded file path or database id (depends on whether you are saving the file to disc or DB)
- retrieve new object id (if needed for some other process)

You probably don't want to create a new business object until you have
the file uploaded server-side. What if someone starts an upload and
cancels or they lose connection? The server side will be left with a business object that
doesn't contain the intended file.


-MindCore

methode
Jan 15, 2009, 3:34 PM
Hi mindcore1,

thanx for reply.

well I save my business object first and then I do the upload process, at least this is my scenario.
Indeed, after my bo has been stored, I enable FileUploadDialog control.

Maybe from my steps above is not so clear, I semplified the procedure.

Thanx

Matteo

methode
Jan 17, 2009, 12:05 PM
Hi all,

from my previous post:




how can I pass values from code behind to the FileUploadDialog parameters?



Thanx a lot

Matteo

Nime
Feb 03, 2009, 6:48 AM
Hi davidhoyt

I got an error in your .zip file when I run:

A Control with an ID of "ctl00_content_FileUploadDialog1" has already been initialized. Please ensure that all Controls have a unique id.

Source: Z:\server controls\ServerControls\Ext\FileUploadDialog.cs Line: 1437

I simply ignore the error, but I have no idea it is a solution or not : )

davidhoyt
Feb 05, 2009, 3:37 AM
I've been meaning to get this out for a while now. Here's an update with some minor fixes/tweaks to the dialog/code.

Devworks
Feb 09, 2009, 3:48 AM
hi,
thanks a lot for the great effort, i added the dll to bin folder, also added the HTTP module sections, but when i get the following error

Could not load file or assembly 'Coolite.Ext.Web, Version=0.7.0.36502,
Culture=neutral, PublicKeyToken=f58c952e9aa5b80a' or one of its dependencies.
The located assembly's manifest definition does not match the assembly
reference. (Exception from HRESULT: 0x80131040)

mindcore1
Feb 09, 2009, 4:59 PM
Hey Devworks:

David is probably using a build of Coolite from SVN and not the latest release on the downloads page. You will probably have to integrate his attachment into your project and recompile Coolite.

-MC

Devworks
Feb 10, 2009, 1:03 AM
thanks a lot man for this help,
i will do what you said and check it out :)

davidhoyt
Feb 12, 2009, 4:32 AM
mindcore (mc) is exactly right.

onurbozkurt
Feb 19, 2009, 5:21 AM
Hi. Is there any sample using PostURL?

pierusch
Feb 19, 2009, 6:07 AM
Tried to use addictionalPostParameters



If ObjVolume.IsPersisted Then
FileUploadDialog1.AdditionalPostParameters.Add("test", objVolume.id.tostring)
End If


but it seems there are problem with serialization:

System.Runtime.Serialization.ObjectManager.GetCons tructor(Type t, Type[] ctorParams) +7545689
System.Runtime.Serialization.ObjectManager.Complet eISerializableObject(Object obj, SerializationInfo info, StreamingContext context) +115

I noticed that AddictionalPostParameters is not tagged as a serializable class. Could that be the problem?
Is there any other way to pass parameters to the file upload control?

Pierluigi

designworxz
Mar 16, 2009, 11:29 PM
How to restrict it to add only one file and how to get uploaded fileName

geoffrey.mcgill
Apr 07, 2009, 2:14 AM
FYI - The <ext:FileUploadField> has been added to the upcoming v0.8 release.

Not a fancy as this File Upload Dialog, but does provide solid functionality.


A FileUploadField sample has been committed to the examples explorer in svn, see


trunk\Coolite.Examples\Examples\Form\FileUploadFie ld\Basic\



I'll link to the live example as soon as we publish v0.8 of the Examples Explorer.


UPDATE: https://examples1.ext.net/#/Form/FileUploadField/Basic/

rcaunt
Aug 20, 2009, 1:18 PM
Has anyone tried this with an MVC project? I am struggling to get it working properly. I can see that the control is being rendered into the page okay but the script that creates the javascript object is not being rendered.

rcaunt
Aug 20, 2009, 2:18 PM
Sorted it, I had no form tag. Now I just need to get the icons passing through MVC routes.

rcaunt
Aug 21, 2009, 9:38 AM
I have got it all working now.

I did find a few bugs when getting everything working how I wanted. In FileUploadModule.cs, about Line 107 in OnProcessPostFile the following line:



Context.Response.Write(string.Format("{'success':false,'error':\"{0}\"}", Coolite.Utilities.StringUtils.Enquote(e.Message))) ;


should read (note the double escaping on {{ and }}):



Context.Response.Write(string.Format("{{'success':false,'error':\"{0}\"}}", Coolite.Utilities.StringUtils.Enquote(e.Message))) ;


The next problem I am trying to fix is that this data is put into the stream but then a ThreadAbortException occurs on Context.Response.End() which causes the Exception HTML to be put into the response (attempted to modify headers) which then measns the JSON object is broken on the client.

amitpareek
Nov 03, 2009, 8:10 AM
Are you guys planning to update it to 1.0?

To Geoff: Will you guys be officially including it in 1.0?

Fabrizio
Jun 08, 2010, 2:38 PM
Hi ,
Hello I'm testing your upload but returns this error

A Control with an ID of "ctl00_content_FileUploadDialog1" has already been initialized. Please ensure that all Controls have a unique id.


The following Control has the same ID as at least one other Control on the Page. All Controls must have a unique ID.


*************************
Control Details
*************************


ID: FileUploadDialog1.
ClientID: ctl00_content_FileUploadDialog1
Type: FileUploadDialog


*************************
Parent Control Details
*************************


ID: content
ClientID: ctl00_content
Type: ContentPlaceHolder

by chance do you know why?

Thanks a lot
Fabrizio

Thangtq
Aug 04, 2010, 9:27 AM
Hi all.
I want to create web user control with type: upload multi file which use on the page (not dialog ).
This control have function same as File Upload Dialog but i want to use it on a page.
Thanks for help.

binhsoledas
Jan 14, 2011, 3:43 AM
Hi All.

I run this project. When use Upload Dialog of Server Control. I can't drag and move more than on full screen. I only move limited on screen.
When use Upload Dialog of Javascript. I can drag and move everyplace on screen. How to change and fix to move every place on screen with Upload Dialog when using Server Control ?
Thanks

markusn
May 27, 2013, 7:19 PM
Is this implementable in v2.0 for MVC? I tried to port it over but the coolite and ext.net references don't quite port over