簡體   English   中英

從 stream 在 c# 中創建縮略圖

[英]Create thumbnail in c# from stream

經過 3 個小時的調試和搜索,我有了這個。

        public Stream ResizeImageToThumbnail(Stream imageStream, int width)
        {
            var image = Image.FromStream(imageStream);

            var height = (width * image.Height) / image.Width;
            var thumbnail = image.GetThumbnailImage(width, height, null, IntPtr.Zero);

            using var thumbnailStream = new MemoryStream();
            thumbnail.Save(thumbnailStream, ImageFormat.Jpeg);
            return thumbnailStream;
        }

問題是,它返回異常

ArgumentException:參數無效。

var image = Image.FromStream(imageStream);

參數為file.OpenFileStream(); 其中fileIFormFile

我沒主意了。

編輯

要求的代碼:


foreach (var item in model.UploadedImages) //item = IFormFile, image only allowed from HTML's end
{
   using var ms = item.OpenReadStream();
   _service.AttachImage(newId, ms, item.FileName);
   ms.Position = 0;
   _service.AttachThumb(newId, ms, item.FileName); //cannot access a closed stream exception
}

編輯 2

AttachThumb 使用封閉的 stream,返回異常(檢查注釋)。 ResizeImageToThumbnail似乎返回關閉的 stream。

public void AttachThumb(Guid id, Stream imageStream, string imageName)
        {
            Post post = GetPost(id);

            ObjectId imageId = _gridFS.UploadFromStream(imageName, ResizeImageToThumbnail(imageStream, 640)); //cannot use closed stream

            post.ImagesThumbs.Add(imageId.ToString());

            var filter = Builders<Post>.Filter.Eq(x => x.Id, id);
            var update = Builders<Post>.Update.Set("ImagesThumbs", post.ImagesThumbs);
            _posts.UpdateOne(filter, update);
        }

        public Stream ResizeImageToThumbnail(Stream imageStream, int width)
        {
            var image = Image.FromStream(imageStream);

            var height = (width * image.Height) / image.Width;
            var thumbnail = image.GetThumbnailImage(width, height, null, IntPtr.Zero);

            using var thumbnailStream = new MemoryStream();
            thumbnail.Save(thumbnailStream, ImageFormat.Jpeg);
            return thumbnailStream;
        }

首先將文件內容復制到 stream 中,然后使用該 stream。 在兩者之間倒帶 stream。 請注意,兩個 Attach* 方法不得異步訪問 stream。 否則,您必須先創建第二個內存副本。

foreach (var item in model.UploadedImages)
{
    // Copy content in to stream
    using (MemoryStream stream = new MemoryStream())
    {
        item.CopyTo(stream);

        // Rewind and use
        stream.Position = 0;
        _service.AttachImage(newId, stream, item.FileName);
        
        // Rewind and use
        stream.Position = 0;
        _service.AttachThumb(newId, stream, item.FileName);
    }
}

正如用戶 Jimi 所指出的,您必須從ResizeImageToThumbnail方法中刪除using子句。 否則,該方法返回一個已經釋放的MemoryStream

public Stream ResizeImageToThumbnail(Stream imageStream, int width)
{
    var image = Image.FromStream(imageStream);

    var height = (width * image.Height) / image.Width;
    var thumbnail = image.GetThumbnailImage(width, height, null, IntPtr.Zero);

    // Bad: using var thumbnailStream = new MemoryStream();
    // Remove using
    var thumbnailStream = new MemoryStream(); 
    thumbnail.Save(thumbnailStream, ImageFormat.Jpeg);
    return thumbnailStream;
}

然后將 stream 放在外面:

public void AttachThumb(Guid id, Stream imageStream, string imageName)
{
    Post post = GetPost(id);

    using var thumbnailStream = ResizeImageToThumbnail(imageStream, 640);
    // rewind stream
    thumbnailStream.position = 0;
    ObjectId imageId = _gridFS.UploadFromStream(imageName, thumbnailStream); 

    ...

您可以通過不讓ResizeImageToThumbnail方法創建 stream 而是在外部創建 stream 並將其作為參數傳遞給ResizeImageToThumbnail來改進此設計。 所以ResizeImageToThumbnail的調用者然后負責創建和處置 stream。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM