Image.FromStream (PostedFile.InputStream) Сбой. (Параметр недействителен.) (AsyncFileUpload)) - PullRequest
5 голосов
/ 23 октября 2009

Я использую AsyncFileUpload (AJAX Toolkit) для загрузки изображений. У меня есть кнопка, которая обрабатывает изменение размера изображения. Некоторое время это работало нормально, но не больше ...

protected void BtnUploadImage_Click(object sender, EventArgs e)
{
    var imageFileNameRegEx = new Regex(@"(.*?)\.(jpg|jpeg|png|gif)$", 
        RegexOptions.IgnoreCase);
    if (!AsyncFileUpload1.HasFile || 
        !imageFileNameRegEx.IsMatch(AsyncFileUpload1.FileName))
    {
        AsyncFileUpload1.FailedValidation = true;
        ErrorLabel.Visible = true;
        return;
    }
    ErrorLabel.Visible = false;

    var file = AsyncFileUpload1.PostedFile.InputStream;

    var img = Image.FromStream(file, false, false);

...
}

Еще одна вещь, которую я нахожу странной: если я попробую изображение размером менее 80 КБ, оно сработает ..!

Мы попытались перезагрузить сервер, но без изменений. Тот же код отлично работает на моей машине. (слышал что раньше ?? :))

Я также пытался сохранить файл на сервере, затем получить файл через Image.FromFile (), но затем я получил «Не удается получить доступ к закрытому файлу».

Как решить эту проблему?

Ответы [ 2 ]

7 голосов
/ 24 октября 2009

Я бы удостоверился, что поток расположен в начале:

var file = AsyncFileUpload1.FileContent;
file.Seek(0, SeekOrigin.Begin);

var img = Image.FromFile(file);

Второе, что нужно проверить: значение requestLengthDiskThreshold. Если не указан этот параметр, по умолчанию используется значение ... да, 80 КБ.

Примечание: imo не должно быть общей разницы, используете ли вы Image для непосредственного чтения файлового потока или если вы используете промежуточный MemoryStream (кроме того факта, что в последнем случае вы фактически загружаете весь файл в память дважды). В любом случае исходный файловый поток будет считан, таким образом, положение потока, права CAS, права доступа к файлу и т. Д. Все еще применяются.

Примечание 2: и да, во что бы то ни стало убедитесь, что эти ресурсы расположены правильно :)

1 голос
/ 23 октября 2009

Это правильно, это не будет работать. Проблема в том, что вы пересекаете управляемую / неуправляемую границу, я недавно столкнулся с тем же. Другие проблемы заключаются в том, что поток не находится прямо там, и Image.FromStream не знает, как с ним справиться.

Решение довольно простое: прочитайте все из PostedFile в MemoryStream (просто используйте new MemoryStream()) и используйте MemoryStream с Image.FromStream. Это решит вашу проблему.

Обязательно правильно используйте using при работе с Image, Graphics и Stream с. Все они реализуют IDisposable, и в среде ASP.NET, при неправильном использовании блоков using, могут и будут приводить к увеличению использования памяти и другим неприятным побочным эффектам в долгосрочной перспективе (а приложения ASP.NET работают очень долго! ).

Решение должно выглядеть примерно так:

using(Stream memstr = new MemoryStream())
{
    // copy to a memory stream
    Stream uploadStream = AsyncFileUpload1.PostedFile.InputStream;
    byte[] all = new byte[uploadStream.Length];
    uploadStream.Read(all, 0, uploadStream.Length);
    memstr.Write(all, 0, uploadStream.Length);
    memstr.Seek(0, SeekOrigin.Begin);
    using(Graphics g = Graphics.FromStream(memstr))
    {
         // do your img manipulation, or Save it.
    }
}

Обновление: проблема с пересечением управляемой границы возникает только в обратном направлении (с использованием потока ответов), кажется, не с потоками загрузки, но я не совсем уверен.

...