Я подозреваю, что не понимаю, где jpegoptim пытается написать свои временные файлы.jpegoptim on ASP.Net - «Ошибка открытия временного файла»
У меня IIS 7.5 работает ASP.NET 4 AppDomain. В этом у меня есть процесс, который оптимизирует JPEGs с jpegoptim как так:
FileHelper.Copy(existingPath, optimizerPath);
var jpegOptimResult = await ImageHelper.JpegOptim(optimizerPath, 30);
Запуск локально я получаю оптимизированное изображение. Запуск на вышеуказанном сервере я получаю:
D: \ WWW \ hplusf.com \ Ь \ пк \ test.jpg 4096x2990 24bit 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;
}
jpegOptimResult является то, что вы видите там, как сообщение об ошибке она производит. И вот ProcessRunner.RunProcess:
public async Task<string> RunProcess(string command, string args,
bool window, bool captureOutput)
{
var processInfo = new ProcessStartInfo(command, args);
if (!window)
makeWindowless(processInfo);
string output = null;
if (captureOutput)
output = await runAndCapture(processInfo);
else
runDontCapture(processInfo);
return output;
}
protected void makeWindowless(ProcessStartInfo processInfo)
{
processInfo.CreateNoWindow = true;
processInfo.WindowStyle = ProcessWindowStyle.Hidden;
}
protected async Task<string> runAndCapture(ProcessStartInfo processInfo)
{
processInfo.UseShellExecute = false;
processInfo.RedirectStandardOutput = true;
processInfo.RedirectStandardError = true;
var process = Process.Start(processInfo);
var output = process.StandardOutput;
var error = process.StandardError;
while (!process.HasExited)
{
await Task.Delay(100);
}
string s = output.ReadToEnd();
s += '\n' + error.ReadToEnd();
return s;
}
Итак:
jpegOptim работает должным образом на моей локальной машине, и оптимизирует файл, так что это не так, как я звоню jpegOptim.
Операция копирования успешно без исключений, так что это не проблема разрешения с чтением пользователя ASP.Net/записи из этого каталога
jpegOptim только оптимизирует и перезаписывает файл, поэтому, если это на самом деле бега под тем же пользователем ASP.Net, у него не должно возникнуть проблемы с записью этого файла, но ...
Непонятно, где jpegOptim пытается записать свой временный файл, поэтому, возможно, основная проблема заключается в том, где записывается этот временный файл ,
Однако, судя по источнику с Windows:
http://sourceforge.net/p/jpegoptim/code/HEAD/tree/jpegoptim-1.3.0/trunk/jpegoptim.c
«временный файл» jpegOptim, как представляется, просто файл назначения при использовании представленных выше опций. Соответствующие линии jpegOptim источника:
int dest = 0;
int main(int argc, char **argv)
{
...
Там некоторый код здесь ищет -d аргумент, который устанавливает Dest = 1 - смысл здесь Dest остается 0. Затем поражает, если ветвь, и положение еще, для Dest = = 0, делает это:
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());
#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");
Так snprintf
, как C# String.Format()
, который должен производить путь:
D: \ WWW \ hplusf.com \ б \ пк \ jpegoptim-1-2.XXXXXX.tmp
Судя по тому, что я могу найти, скорее всего, MKSTEMPS не определен. Значение fopen
называется с «wb» означает, что он записывает двоичный файл, и он возвращает значение null, которое не открывается, и появляется сообщение об ошибке.
Так что - возможные причины:
Плохой путь в TmpDir Вполне возможно, я после C++ плохо (вероятно), но, от взглядов этого он должен быть идентичен исходному пути изображения. Но, возможно, это искалечено для tmpdir, jpegoptim? Входной путь явно чист, потому что jpegoptim фактически испускает его чисто в сообщении об ошибке.
Разрешения выпуск Похоже, маловероятно. Пользователь ASP.Net, в котором он работает, может четко читать и писать, потому что он копирует в каталог перед запуском jpegoptim, и единственным пользователем на компьютере с любыми разрешениями для этого каталога является этот пользователь, поэтому jpegoptim должен был сбить до этого момента если это были разрешения. Это может быть попытка получить доступ к другому директору, но это будет действительно сценарий Bad tmpdir.
Что-то еще, о чем я не думал.
Идеи?
Примечание: Этот вопрос похож:
Using jpegtran, jpegoptim, or other jpeg optimization/compression in C#
Однако этот вопрос с просьбой о совместном окр на GoDaddy, вызывая ответы на спираль вокруг вероятности, он не может раскрутить процессов. У нас есть полный контроль над нашим сервером, и, как должно быть ясно из вышеизложенного, процесс jpegoptim определенно начинается успешно, поэтому это другой сценарий.