在不使用FileUpload服务器控件的情况下在ASP.net中上传文件


99

如何获取ASP.net Web表单(v3.5)以使用普通旧文件发布文件<input type="file" />

我对使用ASP.net FileUpload服务器控件不感兴趣。

Answers:


133

在您的aspx中:

<form id="form1" runat="server" enctype="multipart/form-data">
 <input type="file" id="myFile" name="myFile" />
 <asp:Button runat="server" ID="btnUpload" OnClick="btnUploadClick" Text="Upload" />
</form>

在后面的代码中:

protected void btnUploadClick(object sender, EventArgs e)
{
    HttpPostedFile file = Request.Files["myFile"];

    //check file was submitted
    if (file != null && file.ContentLength > 0)
    {
        string fname = Path.GetFileName(file.FileName);
        file.SaveAs(Server.MapPath(Path.Combine("~/App_Data/", fname)));
    }
}

3
@mathieu,可惜您的变体确实使用了runat="server"它,它并不独立于ASP.NET的服务器内容
秘密

如果输入多于1个并且您想对两组文件执行单独的功能怎么办?
内维尔·纳泽拉内

在使用它上传多个文件时,它对所有文件返回相同的文件名,因此将第一个文件保存n次。知道如何克服它吗?
sohaiby 2015年

@Martina检查此代码段以保存多个文件
sohaiby

1
@DanielJ。如果以后要对文件进行任何操作(即将其存储在数据库中),则不可能使用代码隐藏。当然,您可以使用直接的JavaScript来获取输入和文件:var fileUploaded = document.getElementById("myFile").files[0];甚至可以使用readAsArrayBuffer以下命令获取字节:stackoverflow.com/questions/37134433/…-但是您打算如何处理所有这些字节的客户端?OP希望完全避免ASP.NET控件而不是服务器端的通信。-1给你。
vapcguy

40

这是一个不依赖任何服务器端控制的解决方案,就像OP在问题中描述的那样。

客户端HTML代码:

<form action="upload.aspx" method="post" enctype="multipart/form-data">
    <input type="file" name="UploadedFile" />
</form>

upload.aspx的Page_Load方法:

if(Request.Files["UploadedFile"] != null)
{
    HttpPostedFile MyFile = Request.Files["UploadedFile"];
    //Setting location to upload files
    string TargetLocation = Server.MapPath("~/Files/");
    try
    {
        if (MyFile.ContentLength > 0)
        {
            //Determining file name. You can format it as you wish.
            string FileName = MyFile.FileName;
            //Determining file size.
            int FileSize = MyFile.ContentLength;
            //Creating a byte array corresponding to file size.
            byte[] FileByteArray = new byte[FileSize];
            //Posted file is being pushed into byte array.
            MyFile.InputStream.Read(FileByteArray, 0, FileSize);
            //Uploading properly formatted file to server.
            MyFile.SaveAs(TargetLocation + FileName);
        }
    }
    catch(Exception BlueScreen)
    {
        //Handle errors
    }
}

注意在MyFile.FileName中发送完整文件路径的HTTPWebRequest调用。WebClient调用仅发送文件名。HTTPWebRequest将导致MyFile.SaveAs失败。只是浪费时间追逐一位客户而没有一位客户。
鲍勃·克莱格

我只是用Request.Files[0]代替,Request.Files["UploadedFile"]而OP使用的是纯ASP.NET而不是MVC,如果有人想将其用于MVC,则只需要HttpPostedFileBase使用HttpPostedFile
vapcguy

23

您必须将的enctype属性设置formmultipart/form-data; 那么您可以使用该HttpRequest.Files集合访问上载的文件。


我的服务器表单在母版页上,因此无法添加multipart / form-data(因为它将在每个页面上)。一种快速而又肮脏的解决方法是向页面添加隐藏的FileUpload控件。然后,WebForms自动添加multipart / form-data。我之所以必须这样做是因为我在Angular2中使用了文件输入,并且无法在组件模板中使用服务器控件。
杰森

9

将HTML控件与runat服务器属性一起使用

 <input id="FileInput" runat="server" type="file" />

然后在asp.net中

 FileInput.PostedFile.SaveAs("DestinationPath");

如果您感兴趣,还有一些第三方选项将显示进度


3
同样,这又将其转变为服务器控件。;)
ahwm

@ahwm OP希望避免ASP.NET FileUpload控件(<asp:FileUpload ID="fileUpload1" runat="server"></asp:FileUpload>),这与说不要runat=serverinput字段上放置不同。
vapcguy

1
我认为这表示他们不想使用ASP.NET控件。其中包括HtmlInputFile控件。
ahwm

8

是的,您可以通过ajax post方法来实现。在服务器端,您可以使用httphandler。因此,我们没有根据您的要求使用任何服务器控件。

使用ajax,您还可以显示上传进度。

您将不得不将文件作为输入流读取。

using (FileStream fs = File.Create("D:\\_Workarea\\" + fileName))
    {
        Byte[] buffer = new Byte[32 * 1024];
        int read = context.Request.GetBufferlessInputStream().Read(buffer, 0, buffer.Length);
        while (read > 0)
        {
            fs.Write(buffer, 0, read);
            read = context.Request.GetBufferlessInputStream().Read(buffer, 0, buffer.Length);
        }
    } 

样例代码

function sendFile(file) {              
        debugger;
        $.ajax({
            url: 'handler/FileUploader.ashx?FileName=' + file.name, //server script to process data
            type: 'POST',
            xhr: function () {
                myXhr = $.ajaxSettings.xhr();
                if (myXhr.upload) {
                    myXhr.upload.addEventListener('progress', progressHandlingFunction, false);
                }
                return myXhr;
            },
            success: function (result) {                    
                //On success if you want to perform some tasks.
            },
            data: file,
            cache: false,
            contentType: false,
            processData: false
        });
        function progressHandlingFunction(e) {
            if (e.lengthComputable) {
                var s = parseInt((e.loaded / e.total) * 100);
                $("#progress" + currFile).text(s + "%");
                $("#progbarWidth" + currFile).width(s + "%");
                if (s == 100) {
                    triggerNextFileUpload();
                }
            }
        }
    }

2
也许您应该添加提示,以添加fs.close()其他所有内容,这些内容可能最终会以无法读取的文件形式出现,因为它们在IIS中始终保持打开状态。
mistapink '16

@mistapink执行离开using块时,文件流是否未关闭?
塞比

@Sebi好像差不多3年前没有。长时间没有尝试过,所以在这里我不能给出明确的答案。对不起。
mistapink

4

Request.Files集合包含随您的表单上传的所有文件,无论它们来自FileUpload控件还是手动编写的<input type="file">

因此,您只需在WebForm的中间编写一个普通的旧文件输入标签,然后读取从Request.Files集合上传的文件。


4

正如其他人所回答的那样,Request.Files是一个HttpFileCollection,其中包含所有发布的文件,您只需要向该对象索要以下文件:

Request.Files["myFile"]

但是,当有多个具有相同属性名称的输入标记时会发生什么:

Select file 1 <input type="file" name="myFiles" />
Select file 2 <input type="file" name="myFiles" />

在服务器端,先前的代码Request.Files [“ myFile”]仅返回一个HttpPostedFile对象,而不是两个文件。我在.net 4.5上看到了一个名为GetMultiple的扩展方法,但是对于过时的版本,它不存在,为此,我提出了以下扩展方法:

public static IEnumerable<HttpPostedFile> GetMultiple(this HttpFileCollection pCollection, string pName)
{
        for (int i = 0; i < pCollection.Count; i++)
        {
            if (pCollection.GetKey(i).Equals(pName))
            {
                yield return pCollection.Get(i);
            }
        }
}

此扩展方法将返回HttpFileCollection中名称为“ myFiles”的所有HttpPostedFile对象(如果存在)。


2

HtmlInputFile控件

我一直都在用这个。


2
这就需要添加runat="server",这实际上会将其转变为他们不希望使用的服务器控件。
ahwm 2013年

@ahwm不,OP不想使用特定的ASP .NET FileUpload控件。通常,这与说他们不想使用服务器端控件不同。
vapcguy


0
//create a folder in server (~/Uploads)
 //to upload
 File.Copy(@"D:\CORREO.txt", Server.MapPath("~/Uploads/CORREO.txt"));

 //to download
             Response.ContentType = ContentType;
             Response.AppendHeader("Content-Disposition", "attachment;filename=" + Path.GetFileName("~/Uploads/CORREO.txt"));
             Response.WriteFile("~/Uploads/CORREO.txt");
             Response.End();
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.