简体   繁体   English

无法使用Image对象覆盖C#中上传的图像

[英]Unable to overwrite uploaded images in C# using the Image object

I am trying to create a utility in C# using the MVC framework where a user uploads a picture which is used to crop pieces out of to be used as thumbnail icons (only one user at a time will be doing this at any given time). 我正在尝试使用MVC框架在C#中创建一个实用程序,在该实用程序中,用户上传一张图片,该图片用于裁剪片段以用作缩略图图标(在任何给定的时间一次只有一个用户会这样做)。 The user can then upload a different picture and continue cropping. 然后,用户可以上传其他图片并继续裁剪。

I have a controller action that handles the file upload taking the picture, converting it from whatever format it's in to a jpeg and saving it as "temp.jpg" (I know it's not a thin controller, but this is just for testing purposes). 我有一个控制器操作,用于处理拍摄照片的文件上传,将其从格式转换为jpeg并将其保存为“ temp.jpg”(我知道它不是瘦控制器,但这只是出于测试目的) 。 When they upload the next picture I want to replace that temp.jpg with this new image. 当他们上传下一张图片时,我想用新图像替换该temp.jpg。 This controller works fine in development on my machine, but in production after the user uploads the first image and tries to replace it with another image they get the following error: 该控制器在我的机器上进行开发时工作正常,但是在用户上载第一个图像并尝试将其替换为另一个图像后,在生产环境中出现以下错误:

"the process cannot access the file because it is being used by another process" “该进程无法访问该文件,因为它正在被另一个进程使用”

It seems to me the the "temp.jpg" file is being locked after the first upload and I can't figure out how to avoid this. 在我看来,“ temp.jpg”文件在首次上传后被锁定了,我想不出如何避免这种情况。

Any suggestions or alternative ideas are welcome. 欢迎任何建议或替代想法。

Break down of what my code does: 细分我的代码的作用:

  • Checks if the picture to be uploaded exists on the server and deletes it if found 检查服务器上是否存在要上传的图片,并在找到后将其删除
  • Saves the picture as is with it's original file name and extension 以原始文件名和扩展名原样保存图片
  • Checks for the "temp.jpg" file and deletes it if found 检查“ temp.jpg”文件,如果找到则将其删除
  • Opens the original image in a System.Drawing.Image object to convert to jpeg 在System.Drawing.Image对象中打开原始图像以转换为jpeg
  • Save it as a new "temp.jpg" to replace the deleted file. 将其另存为新的“ temp.jpg”以替换已删除的文件。

My Code: 我的代码:

        [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult PicUpload(DateTime sd, FormCollection collection)
    {
            foreach (string file in Request.Files)
            {
                HttpPostedFileBase hpf = Request.Files[file] as HttpPostedFileBase;
                    if (hpf.ContentLength == 0)
                        continue;
                    string savedFileName = Path.Combine(
                       AppDomain.CurrentDomain.BaseDirectory + "Content\\AdContent\\",
                       Path.GetFileName(hpf.FileName));

                    FileInfo temp = new FileInfo(savedFileName);
                    if (temp.Exists) temp.Delete();

                    hpf.SaveAs(savedFileName);

                    string tempFileName = AppDomain.CurrentDomain.BaseDirectory + "Content\\AdContent\\temp.jpg";

                    temp = new FileInfo(tempFileName);
                    if (temp.Exists) temp.Delete();

                    EncoderParameters codecParams = new EncoderParameters(1);
                    codecParams.Param[0] = new EncoderParameter(Encoder.Quality, 100L);
                    ImageCodecInfo[] encoders;
                    encoders = ImageCodecInfo.GetImageEncoders();

                    Image newPic = Image.FromFile(savedFileName);
                    newPic.Save(tempFileName, encoders[1], codecParams);
                    newPic.Dispose();

                    FileInfo tmp = new FileInfo(savedFileName);
                    if (tmp.Exists) tmp.Delete();
                    return RedirectToAction("Create", new { startdate = String.Format("{0:MM-dd-yyyy}", sd) });
            }
            return RedirectToAction("Create", new { startdate = String.Format("{0:MM-dd-yyyy}", sd) });
    }

It turns out I was not freeing the resources of the image properly in another section of my code that was returning width and height properties of the image. 事实证明,我没有在代码的另一部分中正确释放图像的资源,该部分返回了图像的width和height属性。 Also instead using the Dispose(); 也可以使用Dispose(); method, I put the code into a "using block" instead like so: 方法,我将代码放入“ using块”中,如下所示:

            using (Image newPic = Image.FromFile(savedFileName))
            {
                newPic.Save(tempFileName, encoders[1], codecParams);
            }

This worked like a charm and I can now delete the temp.jpg file with impunity. 这就像一个咒语,我现在可以删除temp.jpg文件而不受惩罚。

System.Drawing.Image.Save() cannot save to the same location the file was opened from: System.Drawing.Image.Save()无法保存到从以下位置打开文件的位置:

From the docs : "Saving the image to the same file it was constructed from is not allowed and throws an exception." 文档中 :“不允许将图像保存到构造该图像的相同文件,并引发异常。”

使用“面板”控件,然后将其保存为BMP,PNG

You can use a uniquely named temporary file for tempFileName instead of "temp.jpg." 您可以对tempFileName使用唯一命名的临时文件,而不要使用“ temp.jpg”。 System.IO.Path has a GetTempFileName() method that you can use for this. System.IO.Path具有可用于此目的的GetTempFileName()方法。

Another option would be to use the GetRandomFileName() method (also in System.IO.Path ) which returns a random path or filename, then it's just a matter of making a small change to your code: 另一个选择是使用GetRandomFileName()方法(同样在System.IO.Path ),该方法返回随机路径或文件名,然后只需对代码做一些小的更改即可:

- string tempFileName = AppDomain.CurrentDomain.BaseDirectory + "Content\\AdContent\\temp.jpg";
+ string tempFileName = AppDomain.CurrentDomain.BaseDirectory + "Content\\AdContent\\" + System.IO.Path.GetRandomFileName();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM