如何在同一 aspx 页面中临时存储图像,而不使用文件系统?

Posted

技术标签:

【中文标题】如何在同一 aspx 页面中临时存储图像,而不使用文件系统?【英文标题】:How to temporarily store a image within same aspx page, not using the filesystem ? 【发布时间】:2015-08-12 23:14:25 【问题描述】:

我正在使用 asp.net 网络表单和 jcrop(文件上传后裁剪图像)..

这个例子我在这里将临时图像存储到文件系统,但是..由于天蓝色我不能(也不会)这样做..

Soo.. 我怎样才能拥有相同的功能而不保存到磁盘?这意味着......如果可能的话,我希望有一个流在整个线上......

public partial class UserConfig : System.Web.UI.Page

    String path = HttpContext.Current.Request.PhysicalApplicationPath + "images\\";

    protected void Page_Load(object sender, EventArgs e)
    

    

    protected void btnUpload_Click(object sender, EventArgs e)
    
        Boolean FileOK = false;
        Boolean FileSaved = false;

        if (Upload.HasFile)
        
            Session["WorkingImage"] = Upload.FileName;
            String FileExtension = Path.GetExtension(Session["WorkingImage"].ToString()).ToLower();
            String[] allowedExtensions =  ".png", ".jpeg", ".jpg", ".gif" ;
            for (int i = 0; i < allowedExtensions.Length; i++)
            
                if (FileExtension == allowedExtensions[i])
                
                    FileOK = true;
                
            
        

        if (FileOK)
        
            try
            
                Upload.PostedFile.SaveAs(path + Session["WorkingImage"]);
                FileSaved = true;
            
            catch (Exception ex)
            
                lblError.Text = "File could not be uploaded." + ex.Message.ToString();
                lblError.Visible = true;
                FileSaved = false;
            
        
        else
        
            lblError.Text = "Cannot accept files of this type.";
            lblError.Visible = true;
        

        if (FileSaved)
        
            pnlUpload.Visible = false;
            pnlCrop.Visible = true;
            imgCrop.ImageUrl = "images/" + Session["WorkingImage"].ToString();
        
    

    protected void btnCrop_Click(object sender, EventArgs e)
    
        string ImageName = Session["WorkingImage"].ToString();
        int w = Convert.ToInt32(W.Value);
        int h = Convert.ToInt32(H.Value);
        int x = Convert.ToInt32(X.Value);
        int y = Convert.ToInt32(Y.Value);

        byte[] CropImage = Crop(path + ImageName, w, h, x, y);
        using (MemoryStream ms = new MemoryStream(CropImage, 0, CropImage.Length))
        
            ms.Write(CropImage, 0, CropImage.Length);
            using (SD.Image CroppedImage = SD.Image.FromStream(ms, true))
            
                string SaveTo = path + "crop" + ImageName;
                CroppedImage.Save(SaveTo, CroppedImage.RawFormat);
                pnlCrop.Visible = false;
                pnlCropped.Visible = true;
                imgCropped.ImageUrl = "images/crop" + ImageName;
            
        
    

    static byte[] Crop(string Img, int Width, int Height, int X, int Y)
    
        try
        
            using (SD.Image OriginalImage = SD.Image.FromFile(Img))
            
                using (SD.Bitmap bmp = new SD.Bitmap(Width, Height))
                
                    bmp.SetResolution(OriginalImage.HorizontalResolution, OriginalImage.VerticalResolution);
                    using (SD.Graphics Graphic = SD.Graphics.FromImage(bmp))
                    
                        Graphic.SmoothingMode = SmoothingMode.AntiAlias;
                        Graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
                        Graphic.PixelOffsetMode = PixelOffsetMode.HighQuality;
                        Graphic.DrawImage(OriginalImage, new SD.Rectangle(0, 0, Width, Height), X, Y, Width, Height, SD.GraphicsUnit.Pixel);
                        MemoryStream ms = new MemoryStream();
                        bmp.Save(ms, OriginalImage.RawFormat);
                        return ms.GetBuffer();
                    
                
            
        
        catch (Exception Ex)
        
            throw (Ex);
        
    


【问题讨论】:

如果你想要一个流,把它放在会话中。您必须小心,因为会话中的太多可能会达到内存屏障并导致应用程序池回收。您可以尝试通过序列化字符串将其序列化为视图状态,但这会随着视图状态膨胀而真正减慢往返速度。 是的@Mark .. 尤其是在 Session 上犯了错误,而且之前还有些 ViewState..,所以不太急于再去那趟旅行 :) due to azure 这需要更多解释。 Azure 是什么让您不愿意将图像存储在磁盘上? 这是一个很好的观点@Sam :) 我已经有一段时间没有在使用 Azure 网站时在文件系统上存储数据了。记住我有一个 非常 上次我试图调整这个来工作时很难。所以......也许你知道一些我不知道的关于在使用 Azure 时在文件系统上存储文件的事情? 我使用 Azure SDK(通过 NuGet 安装)和 Azure 存储 API(CloudStorageAccount、CloudBlobClient、CloudBlobContainer、CloudBlockBlob)。可从 Azure 网站访问 Azure 存储,上传文件后,即可通过标准 URL 访问该文件。 【参考方案1】:

如果你不反对使用 Azure 存储,这里是我使用的一个类。它专为上传图像和 pdf 而设计,但我相信您可以对其进行修改以满足您的需求。

用法:

Dim storage As AzureStorage = New AzureStorage("storage name", "storage key")
    storage.UploadFile("directory name", "filename", fileStream)

上传后,您的文件可通过 url 访问:

http://yourdomain.blob.core.windows.net/container-name/filename

助手类:

Imports System
Imports System.IO

Imports Microsoft.WindowsAzure.Storage
Imports Microsoft.WindowsAzure.Storage.Auth
Imports Microsoft.WindowsAzure.Storage.Blob


'
'   See http://msdn.microsoft.com/en-us/library/dd135715.aspx for naming guidelines.
'

Public Class AzureStorage

    Public Sub New(ByVal storageName As String, ByVal storageKey As String)

        Me.StorageName = storageName
        Me.StorageKey = storageKey

    End Sub



    Private Function GetStorageAccount() As CloudStorageAccount

        Dim result As CloudStorageAccount = New CloudStorageAccount(New StorageCredentials(StorageName, StorageKey), True)

        Return result

    End Function



    Private Function GetBlobContainer(ByVal name As String) As CloudBlobContainer

        Dim account As CloudStorageAccount = GetStorageAccount()
        Dim client As CloudBlobClient = account.CreateCloudBlobClient
        Dim result As CloudBlobContainer = client.GetContainerReference(name)

        result.CreateIfNotExists(BlobContainerPublicAccessType.Blob)

        Return result

    End Function



    Private Function GetBlob(ByVal containerName As String, ByVal name As String) As CloudBlockBlob

        Dim container As CloudBlobContainer = GetBlobContainer(containerName)
        Dim result As CloudBlockBlob = container.GetBlockBlobReference(name)

        Return result

    End Function



    Public Sub UploadFlyer(ByVal fileName As String, ByVal stream As Stream)

        UploadFile("flyers", fileName, stream)

    End Sub



    Public Sub UploadLogo(ByVal fileName As String, ByVal stream As Stream)

        UploadFile("class-logos", fileName, stream)

    End Sub



    Public Sub UploadFile(ByVal containerName As String, ByVal fileName As String, ByVal stream As Stream)

        Dim blob As CloudBlockBlob = GetBlob(containerName, fileName)
        Dim targetMaximumSize As Int32 = 144
        Dim width As Int32 = targetMaximumSize
        Dim height As Int32 = targetMaximumSize
        Dim coefficient As Decimal = 1
        Dim imageStream As Stream = New MemoryStream

        Dim formats As Dictionary(Of String, System.Drawing.Imaging.ImageFormat) = New Dictionary(Of String, Drawing.Imaging.ImageFormat)
        Dim extension As String = Path.GetExtension(fileName).Trim.ToLower

        formats.Add(".jpg", System.Drawing.Imaging.ImageFormat.Jpeg)
        formats.Add(".png", System.Drawing.Imaging.ImageFormat.Png)

        '
        '   Resize source image to max 144px (2") to a side
        '
        If formats.ContainsKey(extension) Then
            Using sourceImage As System.Drawing.Image = System.Drawing.Image.FromStream(stream)
                coefficient = targetMaximumSize / Math.Max(sourceImage.Width, sourceImage.Height)
                If coefficient < 1 Then
                    width = sourceImage.Width * coefficient
                    height = sourceImage.Height * coefficient
                    Using targetImage As System.Drawing.Image = New System.Drawing.Bitmap(width, height)
                        Using graphics As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(targetImage)
                            graphics.DrawImage(sourceImage, targetImage.GetBounds(System.Drawing.GraphicsUnit.Pixel), sourceImage.GetBounds(System.Drawing.GraphicsUnit.Pixel), Drawing.GraphicsUnit.Pixel)
                        End Using
                        targetImage.Save(imageStream, formats(extension))
                    End Using
                Else
                    sourceImage.Save(imageStream, formats(extension))
                End If
            End Using

            imageStream.Seek(0, SeekOrigin.Begin)
            blob.UploadFromStream(imageStream)
        Else
            blob.UploadFromStream(stream)
        End If
        imageStream.Dispose()

    End Sub



    Public Sub DeleteFile(ByVal containerName As String, ByVal fileName As String)

        Dim blob As CloudBlockBlob = GetBlob(containerName, fileName)

        blob.DeleteIfExists(DeleteSnapshotsOption.IncludeSnapshots)

    End Sub



    Public Property StorageName As String = String.Empty

    Public Property StorageKey As String = String.Empty

End Class

【讨论】:

谢谢@Sam :) 明天下午我会完成,因为我必须上床去参加摩洛哥婚礼(dooh!).. 假期不是很有趣 :) 我有一个储藏室已经设置为上传图片,但我喜欢你通过“UploadFile”方法上传的方式.. :) 我明天试试.. 不过.. 我需要两步(两个不同的页面或.. updatepanel 更新以使这项工作:) 正确。此方法需要通过页面重新加载或 XHR 往返服务器。它没有按要求回答问题,但您可能会发现它很有用。我希望婚礼很有趣!

以上是关于如何在同一 aspx 页面中临时存储图像,而不使用文件系统?的主要内容,如果未能解决你的问题,请参考以下文章

在 .aspx 页面上将字节显示为图像

ASP.NET - 如何在浏览器中显示图像而不将图像保存在临时文件中?

如何在临时图像上使用 jCrop?

OpenCV:如何使用 cv::imwrite 保存图像而不覆盖它们

如何跳过 QFile 的 N 行而不将它们临时存储在 QStrings 中?

如何重命名 df 列而不将列列表临时存储到变量中?