在 ASP.net 中上传文件而不使用 FileUpload 服务器控件

Posted

技术标签:

【中文标题】在 ASP.net 中上传文件而不使用 FileUpload 服务器控件【英文标题】:Uploading Files in ASP.net without using the FileUpload server control 【发布时间】:2010-10-08 20:19:49 【问题描述】:

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

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

【问题讨论】:

【参考方案1】:
//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();

【讨论】:

【参考方案2】:

是的,您可以通过 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();
                
            
        
    

【讨论】:

也许您应该添加提示以添加 fs.close() 其他所有内容都可能以无法读取的文件结尾,因为它们在 IIS 中以某种方式保持打开状态。 @mistapink 执行离开 using 块时文件流没有关闭吗? @Sebi 似乎差不多 3 年前它没有。好久没试了,所以在这里无法给出肯定的答案。对不起。【参考方案3】:

这是一个不依赖任何服务器端控件的解决方案,就像 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
    

【讨论】:

注意 HTTPWebRequest 调用在 MyFile.FileName 中发送完整文件路径。 WebClient 调用只发送文件名。 HTTPWebRequest 将导致 MyFile.SaveAs 失败。只是浪费时间追逐一位工作的客户而一位没有工作的客户。 我只使用了Request.Files[0] 而不是Request.Files["UploadedFile"],而OP 使用的是直接的ASP .NET 而不是MVC,如果有人想将它用于MVC,你只需要HttpPostedFileBase 而不是HttpPostedFile.【参考方案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 对象。

【讨论】:

【参考方案5】:

您必须将formenctype 属性设置为multipart/form-data; 然后您可以使用HttpRequest.Files 集合访问上传的文件。

【讨论】:

我的服务器表单在母版页上,我无法添加 multipart/form-data(因为它会在每个页面上)。一个快速而简单的解决方法是在页面中添加一个隐藏的 FileUpload 控件。 WebForms 然后自动添加了 multipart/form-data。我必须这样做,因为我在 Angular2 中使用文件输入,并且无法在组件模板中使用服务器控件。【参考方案6】:

在你的 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)));
    

【讨论】:

@mathieu,可惜你的变种确实使用了runat="server",它并不独立于 ASP.NET 的服务器内容 如果有超过 1 个输入并且您希望对两组文件执行单独的功能,该怎么办。 在使用它上传多个文件时,它为所有文件返回相同的文件名,因此将第一个文件保存 n 次。知道如何克服它吗? @Martina Check this code snippet 保存多个文件 @DanielJ。如果您之后要对文件执行任何操作(即将其存储在数据库中),则没有可能使用代码隐藏。当然,您可以直接使用 javascript 来获取输入和文件:var fileUploaded = document.getElementById("myFile").files[0];,甚至可以使用readAsArrayBuffer:***.com/questions/37134433/… 获取字节——但是您将在客户端处理所有这些字节吗? OP 希望完全避免 ASP .NET 控件而不是服务器端通信。 -1 给你。【参考方案7】:

使用带有 runat 服务器属性的 HTML 控件

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

然后在asp.net Codebehind中

 FileInput.PostedFile.SaveAs("DestinationPath");

如果您有兴趣,还有一些3'rd party 选项会显示进度

【讨论】:

再一次,这就是把它变成一个服务器控件。 ;) @ahwm OP 想要避免使用 ASP .NET FileUpload 控件 (&lt;asp:FileUpload ID="fileUpload1" runat="server"&gt;&lt;/asp:FileUpload&gt;) 这与说不要在 input 字段上放置 runat=server 不同。 我认为这意味着他们不想使用 ASP.NET 控件。其中包括HtmlInputFile 控件。【参考方案8】:

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

所以你可以在你的 WebForm 中间写一个普通的旧文件输入标签,然后读取从 Request.Files 集合上传的文件。

【讨论】:

【参考方案9】:

HtmlInputFile control

我一直都在用这个。

【讨论】:

这需要添加runat="server",这实际上将其变成了他们不想使用的服务器控件。 @ahwm 不,OP 不想使用特定的 ASP .NET FileUpload 控件。这与一般说他们不想使用服务器端控件不同。

以上是关于在 ASP.net 中上传文件而不使用 FileUpload 服务器控件的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET - 如何在浏览器中显示图像而不将图像保存在临时文件中?

ASP.Net中上传文件的几种方法

如何确定当前在 ASP.Net 中是不是有任何文件正在上传?

ASP.Net 文件上传导致使用触发器在更新面板中回发

在 ASP.NET 中流式传输大文件上传

如何使用 Retrofit 在 android 中调用图像上传 Web 服务 (ASP.NET) .asmx 文件