2009-10-23 13 views
5

Tôi đang sử dụng AsyncFileUpload (AJAX Toolkit) để tải lên hình ảnh. Tôi có một Nút xử lý thay đổi kích thước hình ảnh. này đã làm việc tốt cho một thời gian, nhưng không được nữa ...Image.FromStream (PostedFile.InputStream) Không. (Tham số không hợp lệ.) (AsyncFileUpload))

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); 

... 
} 

Một điều mà tôi thấy lạ: Nếu tôi thử một hình ảnh mà là nhỏ hơn 80kb nó hoạt động ..!

Chúng tôi đã cố gắng khởi động lại máy chủ nhưng không thay đổi. Cùng một mã chạy tốt trên máy tính của tôi. (nghe nói rằng trước đây :))

Tôi cũng đã cố gắng lưu tệp trên máy chủ, sau đó lấy tệp Image.FromFile(), nhưng sau đó tôi nhận được "Không thể truy cập tệp đã đóng".

Cách giải quyết vấn đề này?

+0

Có thiếu mã trong đoạn mã của bạn. –

+0

@ Joseph, tôi nghĩ rằng chỉ cần thêm dấu ngoặc kết thúc ở hàm là sai, nó không thể dừng lại ở đó, biến 'img' không được sử dụng. –

+0

Không nghĩ rằng phần còn lại là có liên quan, những gì xảy ra sau khi hình ảnh.TừStream() không thực hiện anyway. –

Trả lời

7

tôi sẽ đảm bảo rằng các dòng được đặt ở đầu:

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

var img = Image.FromFile(file); 

Điều thứ hai để kiểm tra: the requestLengthDiskThreshold thiết lập. Trừ khi được chỉ định, cài đặt này có mặc định là ... có, 80 KB.

Lưu ý: không nên có sự khác biệt tổng thể cho dù bạn sử dụng hình ảnh để đọc luồng tệp trực tiếp hoặc nếu bạn sử dụng MemoryStream trung gian (khác với trường hợp sau bạn thực sự tải toàn bộ tệp vào bộ nhớ hai lần). Dù bằng cách nào, luồng tệp gốc sẽ được đọc từ đó, do đó vị trí phát trực tuyến, quyền CAS, quyền đối với tệp, v.v. vẫn được áp dụng.

Note2: và có, bằng mọi cách đảm bảo các nguồn lực được xử lý đúng cách :)

+1

Cảm ơn, điều đó đã làm việc như một sự quyến rũ. Tôi đã xem xét các cài đặt HttRuntime, nhưng bằng cách nào đó hoàn toàn bỏ qua cài đặt requestLengthDiskThreshold. :( Nhưng một lần nữa bạn tiết kiệm trong ngày: D –

+0

@PeterLillevold làm thế nào để đạt được điều này mà không cần sử dụng bộ công cụ ajax –

+0

@ HeemanshuBhalla đạt được những gì? Bạn phải cụ thể hơn ở đây, câu trả lời của tôi không chỉ áp dụng cho ATK. tải lên hình ảnh nói chung? Nếu vậy, hãy tìm các QA hiện có tại đây trên SO hoặc đặt câu hỏi mới. –

1

Điều này là chính xác, nó sẽ không hoạt động. Vấn đề là bạn đang vượt qua ranh giới được quản lý/không được quản lý, gần đây tôi đã gặp phải điều này. Các vấn đề khác là luồng không trực tiếp ở đó và Image.FromStream không biết cách xử lý nó.

Giải pháp khá đơn giản: đọc mọi thứ từ ĐăngFile vào MemoryStream (chỉ sử dụng new MemoryStream()) và sử dụng MemoryStream với Image.FromStream. Điều này sẽ giải quyết vấn đề của bạn.

Đảm bảo sử dụng đúng cách using khi bạn làm việc với Image, GraphicsStream s. Tất cả chúng thực hiện IDisposable và trong môi trường ASP.NET, không sử dụng khối using đúng cách, có thể và sẽ dẫn đến việc sử dụng bộ nhớ tăng lên và các hiệu ứng phụ khó chịu khác trong thời gian dài (và các ứng dụng ASP.NET chạy rất lâu!).

Giải pháp nên tìm một cái gì đó như thế này:

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. 
    } 
} 

Cập nhật: các crossing quản lý vấn đề ranh giới chỉ xảy ra trong điều ngược lại (sử dụng dòng Response), có vẻ như, không phải với suối Tải lên, nhưng tôi m không hoàn toàn chắc chắn.

+0

Bạn có thể cung cấp ví dụ về cách đọc tất cả các byte vào luồng bộ nhớ không? –

+0

Lưu ý: nó không đảm bảo rằng 'Read' hoạt động. Nếu không, giá trị trả lại chứa số byte thực sự đã đọc. Bạn có thể làm cho mã của bạn mạnh mẽ hơn bằng cách luôn kiểm tra giá trị trả về của 'Read()', hoặc lặp lại cho đến khi tất cả các byte được đọc. – Abel

+0

Đã cố gắng thực hiện điều này: imageID chuỗi; \t \t sử dụng (var mStream = new MemoryStream()) \t { \t \t var uploadStream = AsyncFileUpload1.PostedFile.InputStream; \t \t var all = new byte [uploadStream.Length]; \t \t uploadStream.Read (tất cả, 0, (int) uploadStream.Length); \t \t mStream.Write (tất cả, 0, (int) uploadStream.Length); \t \t mStream.Seek (0, SeekOrigin.Begin); \t \t sử dụng (var img = Image.FromStream (mStream)) \t \t { \t \t \t ImageID = ImageCreation.SaveImage (img, true); \t \t} \t} Nhưng tôi nhận được {"Tham số không hợp lệ."}, Vẫn còn trên Image.FromStream. (Bây giờ ngay cả trên máy địa phương) –