ASP.NETファイルのアップロード

14065 ワード

ASP.NET依赖Netframeworkクラスライブラリは、大量の機能をカプセル化しており、ファイルのアップロードが非常に簡単で、主に以下の3つの基本的な方法があります.
方法1:WebコントロールFileUploadで、Webサイトのルートディレクトリにアップロードします.
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コントロールHtmlInputFileを使用して、Webサイトのルートディレクトリにアップロードします.
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要素で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["file"].FileNameはブラウザによって異なります.IE 8ではクライアントがファイルをアップロードする完全限定名(パス付き)が取得され、グーグルやアップルなどのブラウザではファイル名(パスなし)が取得されます.
2: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でrequestLengthDiskThreshold属性を通じてしきい値(threshold)を設定することができ、そのデフォルト値は256である.つまり、要求内容が256 KBを超えると、ハードディスク(HDD)がキャッシュとして有効になります.このしきい値は、クライアントがコンテンツをアップロードしているかどうかとは関係なく、クライアントからの要求がこの値より大きいことに関心を持っています.従って、ASP.NET 2.0のサーバのメモリは、クライアントの例外要求によって消費されません.もう一つの弊害は、要求がmaxRequestLength(デフォルト4 M)を超えると、ASP.NETプロセッサはこの要求を処理しません.これとASP.NETは異常を投げ出した.これは、ユーザーがファイルをアップロードしすぎると、ASPではない理由だ.NETアプリケーションで指定されたエラーページ(またはデフォルト)は、ASP.NETはまだこのリクエストを処理していません.
もう一つの問題はASPを処理することです.NET大ファイルアップロードのタイムアウト.これは実際には実行時にwebを読み取ることができる.configのhttpRuntimeセクションは、HttpRuntimeSectionオブジェクトに変換するか、Pageを書き換える.OnError()は、HTTPコード(対応コード)が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 Bazinetは、RIAを使用することを推奨しています.多くの場合、従来のFileUploadコンポーネントの代わりにSilverlightまたはFlashのアップロードコンポーネントを推奨します.これらのコンポーネントは、より良いアップロード体験を提供するだけでなく、「input type=「file」ラベルよりもページ上のテキストボックスやボタンがきれいで、この「input type=「file」ラベルはCSSでスタイルを追加できませんが、解決しようとする人もいます.これまでSilverlightを使用した商用アップロードコンポーネントはあまりありませんでしたが、Silverlightでマルチファイルアップロードを行うプログラムの例を示しました.もちろんSilverlightを使うと簡単にマルチスレッドアップロード、ブレークポイントアップロードという機能を実現できますが、これらは私が詳しく議論する内容ではありません.必要があれば自分で見てもいいです.
選択可能なソリューション
〈input type=「file」/〉ラベルを使用して提供できるサポートは限られており、いくつかの特殊なニーズは実現できません.あるいは、簡単に、直接的に実現できません.だからこのような機能を実現するために、私たちは毎回大きな曲がりをしなければなりません.同じ機能を実現するたびに時間を費やして回り道をしないようにするために、市販やオープンソース業界では様々なアップロードコンポーネントが登場し、アップロードコンポーネントはパッケージされた機能を提供し、ファイルアップロード機能を実現する際に楽になりました.例えば、ほとんどのアップロードコンポーネントは、現在のパーセンテージ値を提供するものもあれば、UIを直接または間接的に提供するものもあります.一部のコンポーネントは簡単なUIしか提供していないが、アップロード、削除の管理インタフェースのセットを提供している.また、クライアントの悪意のあるアップロードを防止する機能を提供するコンポーネントもあります.
一番いい方法は、HttpModuleでブロックを分けてファイルを読み取り、ページのアクティブ化状態を維持することです.これにより、タイムアウトが発生しないと同時に、進捗状況を追跡したり、アップロードをキャンセルしたり、HttpHandlerで実現したりすることができ、進捗バーを通じてユーザーに十分なヒントを与えると同時に、開発者がファイルのサイズやアップロード中に発生する可能性のある異常をよりよく制御することができると思います.アップロードコンポーネントはこれらの方法で使用されています.私たちの選択は次のとおりです.
 
  
    FileUploader.NET (MediaChase ,$310 )   
    RadUpload (Telerik ,$249)   
    NeatUpload ( , LGPL ) 

    ······
NeatUploadはASP.NET PipelineのBeginRequestイベントで現在のHttpWorkerRequestオブジェクトをキャプチャし、ReadEntity Bodyなどのメソッドを直接呼び出してクライアントから渡されたデータストリームを取得し、分析と処理を行います.新しいリクエストを使用してポーリングすることで、現在のアップロードのステータスを取得します.NeatUploadおよびその他のオープンソースコンポーネントについては、JeffreyZhaoのASP.を参照してください.NETアプリにファイルをアップロードして、もちろん彼はまたMemba Velodoc XP Editionとswfuploadを言って、書くのがとてもすばらしいです!
HttpWorkerRequest実装の概要
隠れたHttpWorkerRequestを利用して、そのGetPreloadedEntity BodyとReadEntity Bodyの方法で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)  
    {  
    }  
    }