Valums Ajax Upload w/C# ashx возвращает «Индекс вне допустимого диапазона. Должно быть неотрицательным и меньше размера коллекции. ошибка

Я играл со сценарием загрузки AJAX Valum: http://valums.com/ajax-upload/

Это отвечает всем требованиям для меня, не используя ужасный флэш-объект swfupload для одного. У меня есть точка JS в моем сценарии .ashx (который я не могу отлаживать ни за деньги). Это то, что у меня есть в .ashx:

аватар публичного класса: IHttpHandler, System.Web.SessionState.IRequiresSessionState {

public void ProcessRequest (HttpContext context) {
    //Debugger.Break();

string result = "{\"success\":true}";
    string path = HttpContext.Current.Server.MapPath("/client/vault/" + Helpers.CurrentClientHash(context.Session["SessionHash"].ToString()) + "/users/" + context.Session["SessionHash"].ToString() + "/");
    string saveLocation = string.Empty;
    string fileName = string.Empty;

    try
    {
        int length = 4096;
        int bytesRead = 0;
        Byte[] buffer = new Byte[length];

        //This works with Chrome/FF/Safari
        // get the name from qqfile url parameter here
        Debugger.Break();
        fileName = context.Request["params"];
        Debug.Write(fileName);

        saveLocation = context.Server.MapPath(path) + fileName;

        try
        {
            using (FileStream fileStream = new FileStream(saveLocation, FileMode.Create))
            {
                do
                {
                    bytesRead = context.Request.InputStream.Read(buffer, 0, length);
                    fileStream.Write(buffer, 0, bytesRead);
                }
                while (bytesRead > 0);
            }
        }
        catch (UnauthorizedAccessException ex)
        {
            // log error hinting to set the write permission of ASPNET or the identity accessing the code
            result = result.Replace("true","false, \"error\":" + ex.Message + " " + ex.InnerException + " " + ex.StackTrace.ToString());
        }
}
catch
{
    try
        {
            //This works with IE
            fileName = Path.GetFileName(context.Request.Files[0].FileName);
            saveLocation = context.Server.MapPath(path) + fileName;
            context.Request.Files[0].SaveAs(saveLocation);
        }
    catch (Exception ex)
        {
            result = result.Replace("true", "false, \"error\":" + ex.Message + " " + ex.InnerException);
        }
}
context.Response.Write(result);
}

public bool IsReusable {
    get {
        return false;
    }
}

}

Этот код был любезно предложен другим пользователем скрипта Valum, потому что он поставляется с серверной частью PHP. Когда я запускаю загрузчик, я получаю это в консоли:

[uploader] responseText = {"успех":false, "ошибка":индекс вышел за пределы допустимого диапазона. Должно быть неотрицательным и меньше размера коллекции. Имя параметра: индекс }

... и загрузка, конечно, не удалась. Я уверен, что это как-то связано с FileStream, но без полноценной отладки я не могу найти проблему. Я думаю, это может быть из-за того, что файл не подхватывается .ashx, но он находится в параметрах:

снять загрузчик...

Итак, у меня два вопроса, если позволите:

  1. Может ли кто-нибудь сразу увидеть, где и почему я получаю исключение индекса?
  2. Если нет, то как я могу отладить эту вещь? Я не могу просто запустить отладчик из VS2010, потому что не загружается JS. Очевидно, я тоже не могу сразу перейти к ashx... Есть идеи?

Помощь приветствуется :)


person dooburt    schedule 06.08.2011    source источник


Ответы (3)


К сожалению, я так и не решил это. Я удалил скрипт Valams и выбрал Plupload.

Plupload был проще, он поддерживает HTML5, Flash, Gears и BrowserPlus. В конце концов, это было не просто так. Вот рабочий код для тех, кто ищет виджет C# AJAX Uploader:

<script type="text/javascript" src="/js/jquery.min.js"></script>

    <script type="text/javascript" src="http://bp.yahooapis.com/2.4.21/browserplus-min.js"></script>
    <script type="text/javascript" src="/js/plupload.js"></script>

    <script type="text/javascript" src="/js/plupload.html5.js"></script>
    <script type="text/javascript" src="/js/plupload.gears.js"></script>
    <script type="text/javascript" src="/js/plupload.browserplus.js"></script>
    <script type="text/javascript" src="/js/plupload.silverlight.js"></script>
    <script type="text/javascript">
        // Custom example logic
        function $(id) {
            return document.getElementById(id);
        }


        var uploader = new plupload.Uploader({
            runtimes: 'gears,html5,silverlight,browserplus',
            browse_button: 'pickfiles',
            max_file_size: '2mb',
            multi_selection: false,
            url: '/components/uploadify/avatar.ashx',
            silverlight_xap_url: '/js/plupload.silverlight.xap',
            filters: [
                { title: "Image files", extensions: "jpg,gif,png" }
            ]
        });

        uploader.bind('Init', function (up, params) {
            $('filelist').innerHTML = "<div>Current runtime: " + params.runtime + "</div>";
        });

        uploader.bind('FilesAdded', function (up, files) {
            for (var i in files) {
                $('filelist').innerHTML += '<div id="' + files[i].id + '">' + files[i].name + ' (' + plupload.formatSize(files[i].size) + ') <b></b></div>';
            }
        });

        uploader.bind('UploadFile', function (up, file) {
            $('uploader').innerHTML += '<input type="hidden" name="file-' + file.id + '" value="' + file.name + '" />';
        });

        uploader.bind('UploadProgress', function (up, file) {
            $(file.id).getElementsByTagName('b')[0].innerHTML = '<span>' + file.percent + "%</span>";
        });

        uploader.bind('FileUploaded', function (up, file, obj) {
            alert("I've done uploading stuff...");

        });

        $('uploadfiles').onclick = function () {
            uploader.start();
            return false;
        };

        uploader.init();
</script>

И С# .ashx...

public class avatar : IHttpHandler, System.Web.SessionState.IRequiresSessionState {

    public void ProcessRequest (HttpContext context) {
        string path = "/a/path/to/someplace/";
        if (context.Request.Files.Count > 0)
        {
            int chunk = context.Request["chunk"] != null ? int.Parse(context.Request["chunk"]) : 0;
            string fileName = context.Request["name"] != null ? context.Request["name"] : string.Empty;

            HttpPostedFile fileUpload = context.Request.Files[0];

            var uploadPath = path;
            using (var fs = new FileStream(Path.Combine(uploadPath, fileName), chunk == 0 ? FileMode.Create : FileMode.Append))
            {
                var buffer = new byte[fileUpload.InputStream.Length];
                fileUpload.InputStream.Read(buffer, 0, buffer.Length);

                fs.Write(buffer, 0, buffer.Length);
            }
        }

    }

    public bool IsReusable {
        get {
            return false;
        }
    }

}

Возможно, стоит отметить, что если вы хотите получить доступ к сеансу, находясь в .ashx, вам просто нужно добавить SessionState.IRequiresSessionState, как показано.

Я надеюсь, что люди найдут это полезным :)

person dooburt    schedule 08.08.2011

Я использовал обработчик ASHX, который Сайед Башер предоставил в своем . блог. Это работает отлично.

  public void ProcessRequest(HttpContext context)
  {
      const string path = "Capture/Images";
      String filename = HttpContext.Current.Request.Headers["X-File-Name"];
      if (string.IsNullOrEmpty(filename) && HttpContext.Current.Request.Files.Count <= 0)
      {
          context.Response.Write("{success:false}");
      }
      else
      {
          string mapPath = HttpContext.Current.Server.MapPath(path);
          if (Directory.Exists(mapPath) == false)
          {
              Directory.CreateDirectory(mapPath);
          }
          if (filename == null)
          {
              //This work for IE
              try
              {
                  HttpPostedFile uploadedfile = context.Request.Files[0];
                  filename = uploadedfile.FileName;
                  uploadedfile.SaveAs(mapPath + "\\" + filename);
                  context.Response.Write("{success:true, name:\"" + filename + "\", path:\"" + path + "/" + filename + "\"}");
              }
              catch (Exception)
              {
                  context.Response.Write("{success:false}");
              }
          }
          else
          {
              //This work for Firefox and Chrome.
              FileStream fileStream = new FileStream(mapPath + "\\" + filename, FileMode.OpenOrCreate);
              try
              {
                  Stream inputStream = HttpContext.Current.Request.InputStream;
                  inputStream.CopyTo(fileStream);
                  context.Response.Write("{success:true, name:\"" + filename + "\", path:\"" + path + "/" + filename + "\"}");
              }
              catch (Exception)
              {
                  context.Response.Write("{success:false}");
              }
              finally
              {
                  fileStream.Close();
              }
          }
      }
  } 
person sevenkul    schedule 01.12.2011

Я вижу единственный обработчик исключений, который может дать эти результаты, в блоке «Это работает с IE». Единственным индексом, на который ссылается этот блок, является Files[0].

Я предлагаю добавить catch(Exception ex) к первой попытке/пойму, чтобы определить, почему код, работающий с Safari, не работает с IE. Следует также отметить, что вы читаете поток для всех браузеров, а затем пытаетесь перечитать поток только для IE. Это потребует сброса потока в положение 0.

Посмотрите, работает ли этот серверный скрипт со всеми браузерами:

using System;
using System.Web;
using System.IO;
public class Upload : IHttpHandler 
{   
    public void ProcessRequest(HttpContext context) 
    {   
        string path = HttpContext.Current.Server.MapPath("/client/vault/" 
            + Helpers.CurrentClientHash(context.Session["SessionHash"].ToString()) 
            + "/users/" + context.Session["SessionHash"].ToString() 
            + "/");

        HttpPostedFile oFile = 
                    context.Request.Files[context.Request.Headers["X-File-Name"]]; 

        if (!Directory.Exists(path)) Directory.CreateDirectory(path);       
        oFile.SaveAs(path + oFile.FileName);     

        context.Response.Write("1");   
    }   
    public bool IsReusable 
    {      
        get { return true; }   
    }
}
person Chris Gessler    schedule 06.08.2011
comment
Спасибо за ответ, предоставленный вами код sniipet является внутренним скриптом для Uploadify и не будет работать для скрипта Valams. Однако я попробую попробовать/поймать и посмотреть, куда это нас приведет! - person dooburt; 08.08.2011