Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/142.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ASP.Net上的jpegoptim-“;打开临时文件时出错";_C#_C++_Asp.net_Jpegoptim - Fatal编程技术网

C# ASP.Net上的jpegoptim-“;打开临时文件时出错";

C# ASP.Net上的jpegoptim-“;打开临时文件时出错";,c#,c++,asp.net,jpegoptim,C#,C++,Asp.net,Jpegoptim,我怀疑我无法理解jpegoptim试图将其临时文件写入何处 我有运行ASP.Net 4 AppDomain的IIS 7.5。在其中,我有一个使用jpegoptim优化JPEG的过程,如下所示: FileHelper.Copy(existingPath, optimizerPath); var jpegOptimResult = await ImageHelper.JpegOptim(optimizerPath, 30); 在本地运行可以获得优化的图像。在上述服务器上运行时,我得到: D:\ww

我怀疑我无法理解jpegoptim试图将其临时文件写入何处

我有运行ASP.Net 4 AppDomain的IIS 7.5。在其中,我有一个使用jpegoptim优化JPEG的过程,如下所示:

FileHelper.Copy(existingPath, optimizerPath);
var jpegOptimResult = await ImageHelper.JpegOptim(optimizerPath, 30);
在本地运行可以获得优化的图像。在上述服务器上运行时,我得到:

D:\www\hplusf.com\b\pc\test.jpg 4096x2990 24位N Adobe[OK]jpegoptim:打开临时文件时出错

我可以显示
FileHelper.Copy()
的代码,但如果文件已经存在,基本上只会覆盖
File.Copy()

以下是ImageHelper.JpegOptim:

public static async Task<string> JpegOptim(string path, int quality)
{
    string jpegOptimPath = Path.GetDirectoryName(new Uri(Assembly
            .GetExecutingAssembly().CodeBase).LocalPath)
        + @"\Lib\jpegoptim.exe";

    var jpegOptimResult = await ProcessRunner.O.RunProcess(
        jpegOptimPath,
        "-m" + quality + " -o -p --strip-all --all-normal \"" + path + "\"",
        false, true
    );

    return jpegOptimResult;
}
这里有一些代码在寻找设置dest=1的-d参数,这意味着dest仍然为0。然后它点击一个if分支,对于dest==0,else子句执行以下操作:

if (!splitdir(argv[i],tmpdir,sizeof(tmpdir))) 
    fatal("splitdir() failed!");
strncpy(newname,argv[i],sizeof(newname));
这是将输入图像文件名的目录名部分复制到变量
tmpdir
——就像C:\Blah\18.jpg分配
tmpdir=“C:\Blah\”
。然后它将整个输入图像文件名转储到
newname
,这意味着它将在适当的位置覆盖它

在代码的这一点上,它使用的变量应该是:

dest=0
argv[i]=D:\www\hplusf.com\b\pc\test.jpg
tmpdir=D:\www\hplusf.com\b\pc\
newname=D:\www\hplusf.com\b\pc\test.jpg
然后它实际上打开了文件,并且有可能出错,这表明jpegoptim正在成功地打开文件。它还会解压缩文件,进一步确认文件已成功打开

我看到的特定错误消息出现在这些行中-我承认我不知道是否为默认构建(我正在使用)设置了MKSTEMPS:

snprintf(tmpfilename,sizeof(tmpfilename),
“%sjpegoptim-%d-%d.XXXXXX.tmp”,tmpdir,(int)getuid(),(int)getpid();
#如果有
如果((tmpfd=mkstemps(tmpfilename,4))<0)
致命(“创建临时文件时出错:mkstemps()失败”);
if((outfile=fdopen(tmpfd,“wb”))==NULL)
#否则
tmpfd=0;
if((outfile=fopen(tmpfilename,“wb”))==NULL)
#恩迪夫
致命(“打开临时文件时出错”);
因此,
snprintf
类似于C#
String.Format()
,它应该生成如下路径:

D:\www\hplusf.com\b\pc\jpegoptim-1-2.XXXXXX.tmp

根据我所能发现的判断,很可能MKSTEMPS没有定义,这意味着
fopen
被调用时带有“wb”,这意味着它正在写入一个二进制文件,它返回null意味着它无法打开,并且出现了错误消息

因此-可能的原因:

    >P>> TMPDIR 中的坏路径。我有可能遵循C++(可能),但是,从它的外观来看,它应该与图像的源路径相同。但也许它被jpegoptim的tmpdir弄坏了?输入路径显然是干净的,因为jpegoptim实际上在错误消息中干净地发出了它

  • 权限问题似乎不大可能出现。运行此目录的ASP.Net用户可以清楚地读写,因为它在jpegoptim启动之前复制到目录,并且计算机上唯一对此目录具有任何权限的用户是该用户,因此jpegoptim在此之前应该失败(如果是权限)。它可能试图访问不同的目录,但这确实是一个糟糕的tmpdir场景

  • 还有一件我没想到的事

想法

注:此问题类似:


然而,这个问题是关于GoDaddy上的一个共享环境,导致答案围绕着他无法启动进程的可能性螺旋上升。我们完全控制了我们的服务器,从上面可以清楚地看到,jpegoptim进程肯定是成功启动的,所以这是另一种情况。

因为我对jpegoptim的理解是不正确的。它使用的tmpdir是可执行文件的工作目录指向的位置,而不是输入图像所在的位置,也不是可执行文件所在的位置。因此,解决方案是2倍的:

  • 授予exe写入其自己目录*的权限(但拒绝其修改自身的权限)
  • 修改ProcessRunner以就地运行进程-将工作目录设置为exe所在的位置
  • 第二个修改如下所示:

    var processInfo = new ProcessStartInfo(command, args);
    
    // Ensure the exe runs in the path where it sits, rather than somewhere
    // less safe like the website root
    processInfo.WorkingDirectory = (new FileInfo(command)).DirectoryName;
    
    *注意:我碰巧在服务器上将jpegoptim.exe隔离到它自己的目录以限制风险。如果你把它放在一个更全局的地方,比如程序文件,你绝对不应该这样做——而是像上面那样设置工作目录,而是放在一个隔离/安全的地方,比如tmp目录,或者更好的是一个临时磁盘。如果你有它的内存,一个内存驱动器将是最快的

    **第二个注意事项:由于硬盘驱动器和jpegoptim的工作方式,如果tmp位置与输出的最终目的地不在同一磁盘上,则jpegoptim与您可能使用的其他代码之间可能会引入部分竞争条件,这取决于其输出。特别是如果使用同一磁盘,jpegoptim完成后,输出JPEG即完成-操作系统更改其文件表中的条目,但硬盘上的图像数据已写入完成。当tmp和目的地是单独的磁盘时,jpegoptim通过告诉操作系统从tmpdir移动到输出目录来完成。这是一个数据移动,在jpegoptim运行完成后的某个时间完成。如果您的等待代码足够快,它将以不完整的JPEG开始工作

    dest=0
    argv[i]=D:\www\hplusf.com\b\pc\test.jpg
    tmpdir=D:\www\hplusf.com\b\pc\
    newname=D:\www\hplusf.com\b\pc\test.jpg
    
        snprintf(tmpfilename,sizeof(tmpfilename),
            "%sjpegoptim-%d-%d.XXXXXX.tmp", tmpdir, (int)getuid(), (int)getpid());
    #ifdef HAVE_MKSTEMPS
        if ((tmpfd = mkstemps(tmpfilename,4)) < 0) 
            fatal("error creating temp file: mkstemps() failed");
        if ((outfile=fdopen(tmpfd,"wb"))==NULL) 
    #else
        tmpfd=0;
        if ((outfile=fopen(tmpfilename,"wb"))==NULL) 
    #endif
            fatal("error opening temporary file");
    
    var processInfo = new ProcessStartInfo(command, args);
    
    // Ensure the exe runs in the path where it sits, rather than somewhere
    // less safe like the website root
    processInfo.WorkingDirectory = (new FileInfo(command)).DirectoryName;