将图片上传至 Windows Azure 网站

13

我有一个ASP.NET MVC 4应用程序,想要部署到Windows Azure。该应用程序的一部分涉及上传图片。当图片上传完成后,我想把它存储在位于 /pictures/uploaded 的目录中。

我的问题是,在托管在Windows Azure上的应用程序中如何将图片上传到相对路径?到目前为止,我的应用程序已经托管在虚拟机上了。我能够通过使用以下方式完成上述操作:

string path = ConfigurationManager.AppSettings["rootWebDirectory"] + "/pictures/uploaded;

// Get the file path
if (Directory.Exists(path) == false)
  Directory.CreateDirectory(path);

string filePath = path + "/uploaded" + DateTime.UtcNow.Milliseconds + ".png";
filePath = filePath.Replace("/", "\\").Replace("\\\\", "\\");

// Write the picture to the file system
byte[] bytes = GetPictureBytes();
using (FileStream fileStream = new FileStream(filePath, FileMode.Create))
{
  fileStream.Write(bytes, 0, bytes.Length);
  fileStream.Flush();
  fileStream.Close();
}

目前,ConfigurationManager.AppSettings["rootWebDirectory"] 指向一个绝对路径,我相信这是我的问题所在。我无法弄清如何将所有内容切换为相对路径。

谢谢!

4个回答

21
这是如何在Azure中设置的简单描述。请参考此链接:http://geekswithblogs.net/MagnusKarlsson/archive/2012/12/02/how-to-use-azure-storage-for-images.aspx
//编辑:以下是来自我的博客的完整示例(如果博客失效)。
yourViewName.cshtml
 @model List<string>  
 @{
     ViewBag.Title = "Index";
 }

 <h2>Index</h2>
 <form action="@Url.Action("Upload")" method="post" enctype="multipart/form-data">

     <label for="file">Filename:</label>
     <input type="file" name="file" id="file1" />
     <br />
     <label for="file">Filename:</label>
     <input type="file" name="file" id="file2" />
     <br />
     <label for="file">Filename:</label>
     <input type="file" name="file" id="file3" />
     <br />
     <label for="file">Filename:</label>
     <input type="file" name="file" id="file4" />
     <br />
     <input type="submit" value="Submit" />

 </form>

 @foreach (var item in Model) {

     <img src="@item" alt="Alternate text"/>
  }

您的控制器操作

public ActionResult Upload(IEnumerable<HttpPostedFileBase> file)
         {
             BlobHandler bh = new BlobHandler("containername");
             bh.Upload(file);
             var blobUris=bh.GetBlobs();

             return RedirectToAction("Index",blobUris);
         }

你的模型
 public class BlobHandler
     {
         // Retrieve storage account from connection string.
         CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
         CloudConfigurationManager.GetSetting("StorageConnectionString"));

         private string imageDirecoryUrl; 

         /// <summary>
         /// Receives the users Id for where the pictures are and creates 
         /// a blob storage with that name if it does not exist.
         /// </summary>
         /// <param name="imageDirecoryUrl"></param>
         public BlobHandler(string imageDirecoryUrl)
         {
             this.imageDirecoryUrl = imageDirecoryUrl;
             // Create the blob client.
             CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

             // Retrieve a reference to a container. 
             CloudBlobContainer container = blobClient.GetContainerReference(imageDirecoryUrl);

             // Create the container if it doesn't already exist.
             container.CreateIfNotExists();

             //Make available to everyone
             container.SetPermissions(
                 new BlobContainerPermissions
                 {
                     PublicAccess = BlobContainerPublicAccessType.Blob
                 });
         }

         public void Upload(IEnumerable<HttpPostedFileBase> file)
         {
             // Create the blob client.
             CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

             // Retrieve a reference to a container. 
             CloudBlobContainer container = blobClient.GetContainerReference(imageDirecoryUrl);

             if (file != null)
             {
                 foreach (var f in file)
                 {
                     if (f != null)
                     {
                         CloudBlockBlob blockBlob = container.GetBlockBlobReference(f.FileName);
                         blockBlob.UploadFromStream(f.InputStream);
                     }
                 }
             }
         }

         public List<string> GetBlobs()
         {
             // Create the blob client. 
             CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

             // Retrieve reference to a previously created container.
             CloudBlobContainer container = blobClient.GetContainerReference(imageDirecoryUrl);

             List<string> blobs = new List<string>();

             // Loop over blobs within the container and output the URI to each of them
             foreach (var blobItem in container.ListBlobs())
                 blobs.Add(blobItem.Uri.ToString());

             return blobs;
         }
     }

1
有趣。开发环境怎么样? - Sebastián Rojas
2
@SebastiánRojasR,不确定您在问什么,但是猜测可能是“如何在本地开发中使用 Blob 存储?”请查看 https://azure.microsoft.com/zh-cn/documentation/articles/storage-use-emulator/。启动 Azure SDK 中包含的 Azure 存储模拟器,并运行 web.config 转换以将您的 StorageConnectionstring 值替换为 value="UseDevelopmentStorage=true"。 - Magnus Karlsson

10

数据和图像不应存储在网站目录中。这就是为什么有Azure Blob Storage的原因。

Azure通过将网站复制到实例中运行,所以如果存在多个实例,则上传的图像(存储在实例本地)将变得不同步,如果存在冲突,则甚至会丢失图像。

如果您真的想这样做,下面的代码将给您想要的结果:

string path = Server.MapPath("~/pictures/uploaded");

你能详细解释一下吗?你是说Azure Blob存在于虚拟文件夹中吗? - Sebastián Rojas
我们可以选择Azure文件存储吗?哪种方法更好- Blob还是文件存储? - Saravanan

3

这里已经有一些好的回答告诉你如何做你需要的事情。如果您不介意,我想提出一种替代方案。

个人而言,解决类似问题时,我会转向Azure Blob存储。Blob存储是一种极其便宜且快速的存储二进制文件的方法(以文件夹形式结构),完全与当前运行云服务的VM分离。

这将使您在迁移或针对现有应用程序进行开发时获得更多自由,因为您不必随着每次部署迁移上传。Blob存储文件也会在多个Azure数据中心之间进行三倍复制,并且对您不产生额外费用,比您的部署VM更具容错性。

转移到Blob存储还将使您能够在站点离线或VM关闭时访问文件。

您不再处于“共享计算”领域,其中所有资源必须存在于同一台机器上。 Azure是为可扩展性和资源分离而构建的。 Blob存储专门为您在此处尝试做的事情而设计。


-1
string path = HostingEnvironment.MapPath(@"~/pictures/uploaded");

这会导致出现错误,例如“找不到路径的一部分'D:\home\site\wwwroot\Content\ImageUploads<imagefile>'”。 - Georg Patscheider

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接