文件上传问题

时间:2009-06-20 08:40:01

标签: c# asp.net iis upload

我需要客户端(最终用户)通过浏览器上传大文件(例如类似于上传大视频文件的Youtube场景),文件大小不应超过500M字节。

我使用ASP.Net + C#+ VSTS + IIS 7.0作为我的开发平台。有关如何处理大文件上传问题的任何想法或良好做法?任何参考样品或文件都表示赞赏。

5 个答案:

答案 0 :(得分:6)

    <system.web>
        <httpRuntime executionTimeout="300" maxRequestLength="512000" />
    </system.web>

这在IIS7中不起作用! httpRuntime适用于IIS6和下面的版本。在IIS7中允许大文件上传的正确方法是:

1)将以下行添加到web.config文件中:

[Web.config] IIS7的maxAllowedContentLength属性

<system.webServer>
   <security >
      <requestFiltering>
          <requestLimits maxAllowedContentLength="1024000000" />
      </requestFiltering>
   </security>
</system.webServer>

2)然后打开文件C:\ Windows \ System32 \ inetsrv \ config \ applicationHost.config并找到该行:

<section name="requestFiltering" overrideModeDefault="Allow" />

overrideModeDefault应为Allow。

答案 1 :(得分:2)

this related question的答案推荐SWFUploadNeatUpload用于通过浏览器上传大文件。 NeatUpload是一个ASP.NET组件,可能非常适合您的环境。

还有JUpload

答案 2 :(得分:2)

您需要设置 maxRequestLength 以正确处理大文件,并设置 executionTimeout ,以便IIS不会在web.config文件中放弃请求

<system.web>
     <httpRuntime executionTimeout="300" maxRequestLength="512000" />
</system.web>

Jon Gallowy关于上传大文件的文章中有更多详细信息here

以下是MSDN关于在asp.net 2.0中上传文件的文章

答案 3 :(得分:1)

几乎所有处理大量上传的网站都默认使用Adobe Flash。通常它们会回归到简单的浏览器上传,但是在闪存中管理当前上载的进度要容易得多。

答案 4 :(得分:0)

我遇到了这个问题,并找到了基于Jonathan's code here的解决方案。他的代码存在一些问题,但这是我的解决方案。如果你想上传一个像1Gbyte文件这样的大文件,你必须把文件丢弃并通过几个请求发送它(一个请求给出超时)。首先设置客户端和服务器端的最大限制。

<system.webServer>
 <security>
  <requestFiltering>
    <requestLimits maxAllowedContentLength="2147483647" />
  </requestFiltering>
 </security>
<system.webServer>

<system.web>
  <httpRuntime targetFramework="4.5" maxRequestLength="2147483647" />
</system.web>

然后将文件分块,并发送每个chuck,等待响应并发送下一个块。这是javascript和控制器代码。

    <div id="VideoDiv">
        <label>Filename:</label>
        <input type="file" id="fileInput" /><br/><br/>
        <input type="button" id="btnUpload" value="Upload a presentation"/><br/><br/>
        <div id="progressbar_container" style="width: 100%; height: 30px; position: relative; background-color: grey; display: none">
            <div id="progressbar" style="width: 0%; height: 100%; position: absolute; background-color: green"></div>
            <span id="progressbar_label" style="position: absolute; left: 35%; top: 20%">Uploading...</span>
        </div>
    </div>

要查询的Javascript代码,调用控制器并更新进度条:

        var progressBarStart = function() {
            $("#progressbar_container").show();
        }

        var progressBarUpdate = function (percentage) {
            $('#progressbar_label').html(percentage + "%");
            $("#progressbar").width(percentage + "%");
        }

        var progressBarComplete = function() {
            $("#progressbar_container").fadeOut(500);
        }

        var file;

        $('#fileInput').change(function(e) {
            file = e.target.files[0];
        });

        var uploadCompleted = function() {
            var formData = new FormData();
            formData.append('fileName', file.name);
            formData.append('completed', true);

            var xhr2 = new XMLHttpRequest();
            xhr2.onload = function() {
                progressBarUpdate(100);
                progressBarComplete();
            }
            xhr2.open("POST", "/Upload/UploadComplete?fileName=" + file.name + "&complete=" + 1, true);
            xhr2.send(formData);
        }

        var multiUpload = function(count, counter, blob, completed, start, end, bytesPerChunk) {
            counter = counter + 1;
            if (counter <= count) {
                var chunk = blob.slice(start, end);
                var xhr = new XMLHttpRequest();
                xhr.onload = function() {
                    start = end;
                    end = start + bytesPerChunk;
                    if (count == counter) {
                        uploadCompleted();
                    } else {
                        var percentage = (counter / count) * 100;
                        progressBarUpdate(percentage);
                        multiUpload(count, counter, blob, completed, start, end, bytesPerChunk);
                    }
                }
                xhr.open("POST", "/Upload/MultiUpload?id=" + counter.toString() + "&fileName=" + file.name, true);
                xhr.send(chunk);
            }
        }

        $("#VideoDiv").on("click", "#btnUpload", function() {
            var blob = file;
            var bytesPerChunk = 3757000;
            var size = blob.size;

            var start = 0;
            var end = bytesPerChunk;
            var completed = 0;
            var count = size % bytesPerChunk == 0 ? size / bytesPerChunk : Math.floor(size / bytesPerChunk) + 1;
            var counter = 0;
            progressBarStart();
            multiUpload(count, counter, blob, completed, start, end, bytesPerChunk);
        });

这里是上传控制器,用于存储chucnk(“App_Data / Videos / Temp”),然后合并它们并存储在(“App_Data / Videos”)中:

public class UploadController : Controller
{
    private string videoAddress = "~/App_Data/Videos";

    [HttpPost]
    public string MultiUpload(string id, string fileName)
    {
        var chunkNumber = id;
        var chunks = Request.InputStream;
        string path = Server.MapPath(videoAddress+"/Temp");
        string newpath = Path.Combine(path, fileName+chunkNumber);
        using (FileStream fs = System.IO.File.Create(newpath))
        {
            byte[] bytes = new byte[3757000];
            int bytesRead;
            while ((bytesRead=Request.InputStream.Read(bytes,0,bytes.Length))>0)
            {
                fs.Write(bytes,0,bytesRead);
            }
        }
        return "done";
    }

    [HttpPost]
    public string UploadComplete(string fileName, string complete)
    {
        string tempPath = Server.MapPath(videoAddress + "/Temp");
        string videoPath = Server.MapPath(videoAddress);
        string newPath = Path.Combine(tempPath, fileName);
        if (complete=="1")
        {
            string[] filePaths = Directory.GetFiles(tempPath).Where(p=>p.Contains(fileName)).OrderBy(p => Int32.Parse(p.Replace(fileName, "$").Split('$')[1])).ToArray();
            foreach (string filePath in filePaths)
            {
                MergeFiles(newPath, filePath);
            }
        }
        System.IO.File.Move(Path.Combine(tempPath, fileName),Path.Combine(videoPath,fileName));
        return "success";
    }

    private static void MergeFiles(string file1, string file2)
    {
        FileStream fs1 = null;
        FileStream fs2 = null;
        try
        {
            fs1 = System.IO.File.Open(file1, FileMode.Append);
            fs2 = System.IO.File.Open(file2, FileMode.Open);
            byte[] fs2Content = new byte[fs2.Length];
            fs2.Read(fs2Content, 0, (int) fs2.Length);
            fs1.Write(fs2Content, 0, (int) fs2.Length);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message + " : " + ex.StackTrace);
        }
        finally
        {
            if (fs1 != null) fs1.Close();
            if (fs2 != null) fs2.Close();
            System.IO.File.Delete(file2);
        }
    }
}

但是,如果两个用户同时上传具有相同名称的文件,则会出现一些问题,您必须处理此问题。通过阅读responseText,您可以捕获一些错误和异常并修剪它。