asp.netファイルアップロード例のまとめ


ASP.NETは.net frame ewelkクラスに頼って、大量の機能をカプセル化して、ファイルをアップロードするのはとても簡単で、主に以下の3つの基本的な方法があります。
方法の1:WebコントロールFileUploadを使って、ウェブサイトのルートディレクトリにアップロードします。
Test.aspxキーコード:

     <form id="form1" runat="server">
     <asp:FileUpload ID="FileUpload1" runat="server" />
     <asp:Button ID="Button1" runat="server" Text=" " OnClick="Button1_Click" />
     <asp:Label ID="Label1" runat="server" Text="" Style="color: Red"></asp:Label>
     </form>
Test.aspx.csキーコード:

     protected void Button1_Click(object sender, EventArgs e)
     {
         if (FileUpload1.HasFile)
         {
              FileUpload1.SaveAs(Server.MapPath("~/") + FileUpload1.FileName);
              Label1.Text = " !";
         }
     }
方法2:HtmlコントロールHtml InputFileを使って、ウェブサイトのルートディレクトリにアップロードします。
Test.aspxキーコード:

     <form id="form1" runat="server">
     <input type="file" id="file1" runat="server" />
     <asp:Button ID="Button1" runat="server" Text=" " OnClick="Button1_Click" />
     <asp:Label ID="Label1" runat="server" Text="" Style="color: Red"></asp:Label>
     </form>
Test.aspx.csキーコード:

     protected void Button1_Click(object sender, EventArgs e)
     {
         if (file1.PostedFile.ContentLength > 0)
         {
              file1.PostedFile.SaveAs(Server.MapPath("~/") + Path.GetFileName(file1.PostedFile.FileName));
              Label1.Text = " !";
         }
     }
方法3:Html元素<input type=“file”で、Request.Filesを通じてウェブサイトのルートディレクトリにアップロードします。
Test.aspxキーコード:

     <form id="form1" runat="server" enctype="multipart/form-data">
     <input type="file" name="file" />
     <asp:Button ID="Button1" runat="server" Text=" " OnClick="Button1_Click" />
     <asp:Label ID="Label1" runat="server" Text="" Style="color: Red"></asp:Label>
     </form>
Test.aspx.csキーコード:

     protected void Button1_Click(object sender, EventArgs e)
     {
         if (Request.Files["file"].ContentLength > 0)
         {
              Request.Files["file"].SaveAs(Server.MapPath("~/") + Path.GetFileName(Request.Files["file"].FileName));
              Label1.Text = " !";
         }
     }
は2つの違いに注意してください。
一つ:FileUpload.FileNameはクライアントのアップロードファイル名を取得します。file 1.Postedfile.FileNameとRequest.Files.Files.FileNameは別のブラウザの場合は違っています。IE 8で取得したのはクライアントアップロードファイルの完全な限定名(パス付き)です。Google、アップルなどのブラウザの下ではファイル名です。
二:FileUploadコントロールにはHasFile属性があり、ユーザーがファイルをアップロードしたかどうかを判断するために使用されますが、後の2つの方法はアップロードファイルサイズContentLength属性を判断することによって、ユーザがアップロードファイルを選択していない場合、この属性値は0です。
FileUploadのパッケージレベルはより高いが、柔軟性はやや悪いと見られます。
例えば、Asp.netファイルアップロード類(ファイルの拡張子名を取得し、ファイルを保存し、文字の透かしを入れる)

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Drawing;
using System.IO;
using System.Drawing.Imaging;

namespace EC
{
/// <summary>
///
/// </summary>
public class UploadObj
{

public UploadObj()
{
//
// TODO:
//
}
/// <summary>
///
/// </summary>
public enum FileType
{
jpg,gif,bmp,png
}

#region
/// <summary>
///
/// </summary>
/// <param name="filename"> </param>
/// <returns></returns>
public static string GetFileExtends(string filename)
{
string ext = null;
if (filename.IndexOf('.') > 0)
{
string[] fs = filename.Split('.');
ext = fs[fs.Length - 1];
}
return ext;
}
#endregion

#region
/// <summary>
///
/// </summary>
/// <param name="fileExtends"> </param>
/// <returns></returns>
public static bool CheckFileExtends(string fileExtends)
{
bool status = false;
fileExtends = fileExtends.ToLower();
string[] fe = Enum.GetNames(typeof(FileType));
for (int i = 0; i < fe.Length; i++)
{
if (fe[i].ToLower() == fileExtends)
{
status = true;
break;
}
}
return status;
}
#endregion

#region
/// <summary>
///
/// </summary>
/// <param name="fpath"> ,Server.MapPath()</param>
/// <param name="myFileUpload"> </param>
/// <returns></returns>
public static string PhotoSave(string fpath,FileUpload myFileUpload)
{
string s = "";
string fileExtends = "";
string fileName = myFileUpload.FileName;
if (fileName != "")
{
//
fileExtends = EC.UploadObj.GetFileExtends(fileName);
if (!EC.UploadObj.CheckFileExtends(fileExtends))
{
EC.MessageObject.ShowPre(" ");
}
Random rd = new Random();
s = EC.RandomObject.DateRndName(rd) + "." + fileExtends;
string file = fpath + "\" + s;
try
{
myFileUpload.SaveAs(file);
}
catch (Exception ee)
{
throw new Exception(ee.ToString());
}
}
return s;
}

#endregion

#region

/// <summary>
///
/// </summary>
/// <param name="fileName"> ( )</param>
/// <param name="text"> </param>
public void AddTextToImg(string fileName, string text)
{
if (!File.Exists(fileName))
{
throw new FileNotFoundException(" ");
}
if (text == string.Empty)
{
return;
}
//

System.Drawing.Image image = System.Drawing.Image.FromFile(fileName);
Bitmap bitmap = new Bitmap(image, image.Width, image.Height);
Graphics g = Graphics.FromImage(bitmap);
float fontSize = 12.0f;//
float textWidth = text.Length * fontSize;//
// ,
float rectX = 0;
float rectY = 0;
float rectWidth = text.Length * (fontSize + 8);
float rectHeight = fontSize + 8;
//
RectangleF textArea = new RectangleF(rectX, rectY, rectWidth, rectHeight);
Font font = new Font(" ", fontSize);//
Brush whiteBrush = new SolidBrush(Color.White);// ,
Brush blackBrush = new SolidBrush(Color.Black);// ,
g.FillRectangle(blackBrush, rectX, rectY, rectWidth, rectHeight);
g.DrawString(text, font, whiteBrush, textArea);
MemoryStream ms = new MemoryStream();
bitmap.Save(ms, ImageFormat.Jpeg);
// , ,
//Response.Clear();
//Response.ContentType = "image/jpeg";
//Response.BinaryWrite(ms.ToArray());
g.Dispose();
bitmap.Dispose();
image.Dispose();
}
#endregion
}
}

ASP.NETの弊害
ASP.NET処理ファイルのアップロードの最大の問題は、メモリの占有率が高すぎて、ファイル全体をメモリにロードして処理するため、ユーザーがファイルをアップロードするのが大きすぎたり、同時にアップロードするユーザが多すぎたりすると、サーバ端末のメモリが使い果たしてしまいます。この観点は一面的で、初期のASP.NET 1.Xに対しては、プログラム処理のためにユーザーがアップロードした内容を完全にメモリにロードすることが問題になりますが、ASP.NET 2.0ではユーザーがアップロードしたデータが一定数を超えた後にハードディスクに一時的なファイルに保存されています。これは開発者にとって完全に透明です。つまり、開発者は以前のようにデータストリームの処理を行うことができます。これもhttpRuntimeにおいてrequest LengthDiskThresold属性によって閾値を設定します。そのデフォルト値は256です。つまり要求内容が256 KBを超えると、ハードディスクがキャッシュされます。この閾値はクライアントがアップロードしているかどうかは関係ありません。クライアントからの要求のみがこの値より大きいことに関心があります。このため、ASP.NET 2.0でサーバのメモリはクライアントの異常要求によって使い果たしません。もう一つの欠点は、要求がmaxRequest Length(デフォルト4 M)を超えた場合、ASP.NET処理プログラムはこの要求を処理しないことです。これはASP.NETが投げた異常とは全く違っています。これはなぜユーザーがファイルをアップロードするには大きすぎて、ASP.NETアプリケーションで指定されたエラーページ(またはデフォルト)ではないのですか?ASP.NETはまだこの要求を処理していません。
もう一つの問題はASP.NETファイルのアップロードのタイムアウトを処理することです。これは、実行時にweb.co.figのhttpRuntime節を読み出し、HttpRuntimeSectionオブジェクトに変換するか、またはPage.OnError()を書き換えることにより、HTTP Code(該当コード)が400であるかどうかを検出することができ、ここではもはや説明しない。
コードは以下の通りです

    System.Configuration.Configuration  
    config = WebConfigurationManager. 
    OpenWebConfiguration("~"); 
    HttpRuntimeSection section = config.GetSection 
    ("system.web/httpRuntime") as HttpRuntimeSection; 
    double maxFileSize = Math.Round 
    (section.MaxRequestLength / 1024.0, 1); 
    string errorString = string.Format("Make sure  
    your file is under {0:0.#} MB.", maxFileSize);

    protected override void OnError(EventArgs e) 
    { 
    HttpContext ctx = HttpContext.Current; 
    Exception exception = ctx.Server.GetLastError (); 

    string errorString =  
     "
    Offending URL: " + ctx.Request.Url.ToString () + 
     "
    Source: " + exception.Source +  
     "
    Message: " + exception.Message + 
     "
    Stack trace: " + exception.StackTrace; 

    ctx.Response.Write (errorString); 

    ctx.Server.ClearError (); 

    base.OnError (e); 
    }

ファイルアップロードの機能には特別な需要が必要です。例えば、プログレスバーのヒントがあれば、ASP.NETパッケージのコントロール〈asp:FileUpload/〉は無力です。
良い解決策
Robert Bazinnetでは、最も良い解決策はRIAを使用することであり、多くの場合、SilverlightまたはFlashのアップロードコンポーネントを伝統的なFileUploadコンポーネントの代わりに使うことを提案しています。このようなコンポーネントはアップロード体験だけでなく、選択可能なソリューション
「input type=「file」/」ラベルを使って提供できるサポートは非常に限られています。いくつかの特殊な需要は実現できません。ですから、このような機能を実現するために、毎回大きなカーブを回ります。同じ機能を実現するたびに時間をかけて回り道をすることを避けるために、市場やソース業界では様々なアップロードコンポーネントが現れ、アップロードコンポーネントはパッケージの良い機能を提供し、ファイルアップロード機能を実現する時に多くの楽になりました。例えば、アップロードコンポーネントのほとんどが直接または間接的にプログレスプロンプトの機能を提供し、現在のパーセンテージ値を提供し、あるものは直接UIセットを提供する。一部のコンポーネントは簡単なUIだけを提供していますが、一部はアップロード、削除の管理インターフェースを提供しています。また、クライアントから悪意のあるアップロードを防ぐ機能を提供するコンポーネントもあります。
最高の方法は、HttpModuleでファイルをブロック分けて読み込み、ページのアクティブ状態を維持することで、タイムアウトしないと思います。また、進捗を追跡したりアップロードをキャンセルしたり、HttpHandlerを通じて実現したりして、プログレスバーを通じてユーザーに十分にヒントを与えると同時に、開発者にファイルサイズとアップロード過程で発生する可能性のある異常をよりよくコントロールさせることができます。アップロードコンポーネントは全部これらの方法を使っています。私達の選択はあります。

    FileUploader.NET (MediaChase ,$310 )  
    RadUpload (Telerik ,$249)  
    NeatUpload ( , LGPL )
    ・・・・・・
Neat Uploadは、ASP.NET PipelineのBeginaRequestイベントで現在のHttpWorkerRequestオブジェクトを切り取り、そのReadEntityBodyを直接呼び出して、クライアントからのデータストリームを取得し、分析し、処理します。新しい要求をポーリングして現在のアップロード状態を取得する。Neat Uploadと他のオープンソースコンポーネントの紹介については、JeffreyZhaoのASP.NETアプリケーションにファイルをアップロードします。もちろん、彼はMemba Velodoc XPエディションとswfuploadも参照してください。とても素晴らしいです。
HttpWorkerrequestの実現紹介
暗黙的なHttpWorkerRequestを利用して、そのGet PrloadEntityBodyとReadEntityBodyの方法でIISからASP.NETのために確立されたpipeのブロックにデータを読み取り、ファイルアップロードを実現することができます。実現方法は以下の通りです。

    IServiceProvider provider=(IServiceProvider) 
    HttpContext.Current; 
    HttpWorkerRequest wr=(HttpWorkerRequest) 
    provider.GetService(typeof(HttpWorkerRequest)); 
    byte[] bs=wr.GetPreloadedEntityBody(); 
    if(!wr.IsEntireEntityBodyIsPreloaded()) 
    { 
    int n=1024; 
    byte[] bs2=new byte[n]; 
    while(wr.ReadEntityBody(bs2,n) 〉0) 
    { 
    } 
    }