文件存在时“无法打开流:没有此类文件或目录”的可能原因

Post Moved to: Network timing issues causing PHP to throw "failed to open stream: No such file or directory"

edit: It should be noted that this code was already in place and working for some time. We switch our server configuration from a single mail server with the images stored locally, to a load balanced configuration with a shared NAS box where the images are stored. Then php started to intermittently say the file doesn't exists.

99% of the time when you get an error saying the file doesn't exist, the file doesn't exist, there is a typo or some such.

We have a .Net site which uploads a file to a temporary location. We then send a request to a php application passing in the temporary file. The php app should then move the file from its temporary location to its permanent location.

We know the file exists, because, in .Net, before sending the request to the php application, we are getting a FileInfo object on the file, and checking FileInfo.Exists,

if .Net determines that the file does exist, it sends the filepath as a parameter in a webrequest to the php application.

However, intermittently, about 2 out of 3 times, the php application gives the following error:

"failed to open stream: No such file or directory"

The fact that it is happening intermittently, .Net says it exists, and we can navigate to the location on disk and verify, indicates that yes, the file does actually exists.

So, what are some other possibilites for why php would throw this exception?

.Net:

public void Save(string tempPath, string username, string password, bool deleteSrc, string merakController = "", string fileNamePrefix = "")
        {
            FileInfo fi = new FileInfo(tempPath);
            if (fi.Exists)
            {
                Name = (fileNamePrefix ?? string.Empty) + fi.Name;
                FileSize = fi.Length;
                TimeStamp = fi.LastWriteTimeUtc;
                string path = fi.FullName;

                if (string.IsNullOrEmpty(Type))
                    throw new Exception("Attachment Type not set");

                IceWarpGroupware_Http gwh = new IceWarpGroupware_Http(username, password);
                string parameters = string.Format("AttName={0}&AttType={1}&AttDesc={0}&AttSize={2}&AttTime={3}", Name, Type, FileSize, Time);
                bool result = gwh.AddAttachment(m_oid, path, parameters, string.Empty, merakController);

                if (!result)
                    throw new Exception("Unable to add attachment \"" + Name + "\"");

                try
                {
                    if (deleteSrc)
                        fi.Delete();
                }
                catch { }
            }
            //else
              //  throw new Exception("Temp file not found");
        }

php:

public function AddAttachment($itemID, $src, $parameters, $value)
    {

        //base64 encode necessary parameters.
        $parameters64 = $this->getBase64(urldecode($parameters));
        $value64 = $this->getBase64($value);

        //Per the API documentation, ADD first, then LOCK, then move manually and then UNLOCK.
        $result = $this->FetchComObject()->FunctionCallBase64('AddAttachment', $this->gsid64, $this->getBase64($itemID), $parameters64, $value64);  //Add the attachment.
        $dest = $this->lockAttachment($this->gsid64, $this->getBase64($itemID), $result);  //Lock the attachment and get the destination path.

        //This is an enhanced version of the file copy routine for error handling if necessary.  Please let alone and commented out when not in use.
        // if (!copy($src, $dest))
        // {
            // if (isset($GLOBALS['php_errormsg']) && !empty($GLOBALS['php_errormsg']))
                // throw new RuntimeException($GLOBALS['php_errormsg']);
            // throw new RuntimeException("File copy failed with an undefined error. [".$src."]");
        // }

        $copySuccess = copy($src, $dest);  //Comment this line out if using the enhanced file copy above.
        //unlink($src);

        $success = $this->unlockAttachment($this->gsid64, $this->getBase64($itemID), $result);  //Unlock the attachment.
        if ($copySuccess == true)
            return true;
        return false;
    }