How can I wait for a media file to become available before running an Update command?

Former Member
Former Member

I am getting the following error message when I try to Update a media file right after it is created. How can I check or wait for the file to become available before calling the Update command? 

System.IO.IOException: The process cannot access the file '\\?\C:\Pl\filestorage\telligent.evolution.components.attachments\13\01\00\00\00\00\01\15\Pl-0454.jpg' because it is being used by another process.





Edited
[edited by: IbrahimK at 12:29 PM (GMT 0) on Tue, Mar 30 2021]
Parents
  • You could:

    1. Adjust the logic of your process to operate serially (at least for a single user).
    2. Add error handling to delay and retry a certain number of times when the file is locked before throwing an error.

    Most often, I've seen this error in development, when the developer had the file open for previewing and attempted to modify the file. Files are written when committed via a create/update API call and the process is complete when the API returns.

  • Former Member
    0 Former Member in reply to Ben Tiedt
    Add error handling to delay and retry a certain number of times when the file is locked before throwing an error.

    How would I achieve this in Velocity?

  • Could you share details about the code creating/updating the file and accessing it that is causing the issue?

  • Former Member
    0 Former Member in reply to Ben Tiedt

    It is the Media gallery - Drag and Drop - finalize script shown below. I make calls to a widget extension in the code.

    #if ($core_v2_page.IsPost)
    	$core_v2_page.SetContentType('application/json')
    
    	#set($fileName = $core_v2_page.GetFormValue('FileName'))
    	#set($galleryId = $core_v2_utility.ParseInt($core_v2_page.GetFormValue('GalleryId')))
    	#set($fileContextId = false)
    	#set($fileContextId = $core_v2_page.GetFormValue('FileContextId'))
    
    	#set($options = "%{}")
    	$options.Add('Name', $fileName)
    	#set($contentType = $core_v2_ui.GetMimeType($fileName))
    	$options.Add('FileUploadContext',$fileContextId)
    	$options.Add('FileName',$file.Name)
    	$options.Add('ContentType', $contentType)
    	$options.Add('_ExtendedAttributes', $contentType)
    
    	#set($media = false)
    	#set($media = $core_v2_media.Create($galleryId, $fileName, $contentType, $fileName, $options))
    	
    	$options.Add('IsApproved', false)
    	$options.Add('_ExtendedAttributes_WatermarkedVersion', $media.id)
    	
    	#set($mediaDownload = $core_v2_media.Create($galleryId, $fileName, $contentType, $fileName, $options))
    	
        #set($byteArray = $ibby_v1_ImageManipulation.AddWatermark($media.File.FileUrl))
        #set($title = $ibby_v1_ImageManipulation.ExtractTitle($media.File.FileUrl))
        #set($tags = $ibby_v1_ImageManipulation.ExtractKeywords($media.File.FileUrl))
        
        #if($title == '')
            $title = $fileName
        #end
    	
    	#set($media1 = $core_v2_media.Update($galleryId, $media.Id, "%{ ContentType = $contentType, FileName = $fileName, FileData = $byteArray, Name = $title, _ExtendedAttributes_DownloadVersion = $mediaDownload.Id, Tags = $tags }"))
    
    	#if($media.HasErrors())
    		$core_v2_page.SendJsonError($media.Errors)
    	#end
    	
    	#if ($media.IsApproved)
    		$core_v2_media.SetSubscribed($media.Id, true)
    	#end
    	
    	{"redirectUrl":"$core_v2_encoding.JavascriptEncode($media.Url)"}
    #end

  • The double core_v2_media.Create calls and core_v2_media.Update with a byte array seem to work fine in my tests. The ibby_v1_ImageManipulation API is custom. Is it possible that these APIs are not properly managing files (disposing of file streams, for example)?

  • Former Member
    0 Former Member in reply to Ben Tiedt
    Is it possible that these APIs are not properly managing files (disposing of file streams, for example)?

    It is possible. Please take a look and let me know if you spot anything suspicious:

          public string ExtractTitle(string url)
            {
    
                ICentralizedFile file = null;
    
                if (CentralizedFileStorage.IsCentralizedFileUrl(url))
                    file = CentralizedFileStorage.GetCentralizedFileByUrl(url);
    
    
                string path = ConfigurationManager.ConnectionStrings["FileStorage"] + file.FileStoreKey + "\\" + file.Path.Replace(".", "\\") + "\\" + file.FileName;
    
                var adapter = new JpegMetadataAdapter(path);
    
                return adapter.Metadata.Title;
            }
       
    
            public string ExtractKeywords(string url)
            {
    
                ICentralizedFile file = null;
    
                if (CentralizedFileStorage.IsCentralizedFileUrl(url))
                    file = CentralizedFileStorage.GetCentralizedFileByUrl(url);
    
    
                string path = ConfigurationManager.ConnectionStrings["FileStorage"] + file.FileStoreKey + "\\" + file.Path.Replace(".", "\\") + "\\" + file.FileName;
    
                var adapter = new JpegMetadataAdapter(path);
    
                return String.Join(", ", adapter.Metadata.Keywords);
            }
    		
    		public static byte[] DrawMultilineWatermark(string url)
        {
    
            ICentralizedFile file = null;
    
            if (CentralizedFileStorage.IsCentralizedFileUrl(url))
                file = CentralizedFileStorage.GetCentralizedFileByUrl(url);
    
    
            using (var bitmap = new Bitmap(file.OpenReadStream()))
            using (var gr = bitmap.GetAdvancedGraphics())
            using (var textPath = new Path())
            {
                var watermarkColor = new RgbColor(255, 255, 255, 145);
    
                var fontSize = UnitConverter.ConvertPixelsToUnits(bitmap.DpiY, bitmap.Height, Unit.Point) / 20.0f;
    
                var watermarkText = string.Format("<span style=\"font-size:{0}pt\">© {1} Stock Photo Site.</span>", (int)(fontSize / 2), DateTime.Now.Year);
    
                var text = new PlainText(watermarkText, gr.CreateFont("Arial", fontSize));
                text.Alignment = TextAlignment.Right;
                text.Leading = 1;
    
                textPath.DrawText(text);
    
                var rect = new RectangleF(0, 0, bitmap.Width, bitmap.Height);
    
                float offset = text.GetBlackBox().Width / 2;
    
                using (var tiledTextPath = TilePathText(textPath, rect, offset))
                {
                    gr.FillPath(new SolidBrush(watermarkColor), tiledTextPath);
                    /*
                    for (float i = offset; i < bitmap.Width; i += offset / 2)
                    {
                        gr.DrawEllipse(new Pen(watermarkColor, 3), -i, rect.Height - i, i * 2, i * 2);
                        gr.DrawEllipse(new Pen(watermarkColor, 3), rect.Width - i, rect.Height - i, i * 2, i * 2);
                    }*/
                }
    
                System.IO.MemoryStream stream = new System.IO.MemoryStream();
                bitmap.Save(stream, new Aurigma.GraphicsMill.Codecs.BmpSettings());
    
                return stream.ToArray();
            }
        }

  • Debugging custom code and 3rd party components is out of scope for support here, but, I will note a few things to consider:

    1. Disable the metadata calls and try the completion script with no calls and then try each call individually to see if it is an issue with a specific call.
    2. Looking at your custom code, I would recommend using stream instead of ever trying to recreate a local file path -- that path generation logic is not supported and could change.
Reply Children
No Data