Не удалось преобразовать (некоторые) eps в png с помощью ImageMagick (Firebase Cloud Function) - PullRequest
0 голосов
/ 11 января 2019

У меня проблема с некоторыми преобразованиями EPS, использующими ImageMagick в Firebase Cloud Functions. Те, которые работают, работают каждый раз - а те, которые не работают, всегда терпят неудачу, и я не понимаю, почему ..

Я получаю эту ошибку в журналах:

{ ChildProcessError: `convert -colorspace sRGB -density 300 input.eps -resize 400x400 output.png` failed with code 1
    at ChildProcess.<anonymous> (/user_code/node_modules/child-process-promise/lib/index.js:132:23)
    at emitTwo (events.js:106:13)
    at ChildProcess.emit (events.js:191:7)
    at maybeClose (internal/child_process.js:920:16)
    at Socket.<anonymous> (internal/child_process.js:351:11)
    at emitOne (events.js:96:13)
    at Socket.emit (events.js:188:7)
    at Pipe._handle.close [as _onclose] (net.js:509:12)
  name: 'ChildProcessError',
  code: 1,
  childProcess: 
   ChildProcess {
     domain: null,
     _events: { error: [Function: t], close: [Function] },
     _eventsCount: 2,
     _maxListeners: undefined,
     _closesNeeded: 3,
     _closesGot: 3,
     connected: false,
     signalCode: null,
     exitCode: 1,
     killed: false,
     spawnfile: 'convert',
     _handle: null,
     spawnargs: 
      [ 'convert',
        '-colorspace',
        'sRGB',
        '-density',
        '300',
        'input.eps',
        '-resize',
        '400x400',
        'output.png' ],
     pid: 12,
     stdin: 
      Socket {
        connecting: false,
        _hadError: false,
        _handle: null,
        _parent: null,
        _host: null,
        _readableState: [Object],
        readable: false,
        domain: null,
        _events: [Object],
        _eventsCount: 2,
        _maxListeners: undefined,
        _writableState: [Object],
        writable: false,
        allowHalfOpen: false,
        destroyed: true,
        _bytesDispatched: 0,
        _sockname: null,
        _pendingData: null,
        _pendingEncoding: '',
        server: null,
        _server: null,
        write: [Function: writeAfterFIN],
        _idleNext: null,
        _idlePrev: null,
        _idleTimeout: -1 },
     stdout: 
      Socket {
        connecting: false,
        _hadError: false,
        _handle: null,
        _parent: null,
        _host: null,
        _readableState: [Object],
        readable: false,
        domain: null,
        _events: [Object],
        _eventsCount: 3,
        _maxListeners: undefined,
        _writableState: [Object],
        writable: false,
        allowHalfOpen: false,
        destroyed: true,
        _bytesDispatched: 0,
        _sockname: null,
        _pendingData: null,
        _pendingEncoding: '',
        server: null,
        _server: null,
        _idleNext: null,
        _idlePrev: null,
        _idleTimeout: -1,
        write: [Function: writeAfterFIN] },
     stderr: 
      Socket {
        connecting: false,
        _hadError: false,
        _handle: null,
        _parent: null,
        _host: null,
        _readableState: [Object],
        readable: false,
        domain: null,
        _events: [Object],
        _eventsCount: 3,
        _maxListeners: undefined,
        _writableState: [Object],
        writable: false,
        allowHalfOpen: false,
        destroyed: true,
        _bytesDispatched: 0,
        _sockname: null,
        _pendingData: null,
        _pendingEncoding: '',
        server: null,
        _server: null,
        write: [Function: writeAfterFIN],
        read: [Function],
        _consuming: true,
        _idleNext: null,
        _idlePrev: null,
        _idleTimeout: -1 },
     stdio: [ [Object], [Object], [Object] ] },
  stdout: undefined,
  stderr: undefined }

Моя облачная функция выглядит так:

/**
 * When an image is uploaded in the Storage bucket We generate a thumbnail automatically using
 * ImageMagick.
 * After the thumbnail has been generated and uploaded to Cloud Storage,
 * we write the public URL to Firestore.
 */
exports.generateThumbnail = functions.storage.object().onFinalize((object) => {
  // File and directory paths.
  const filePath = object.name;
  const contentType = object.contentType; // This is the image MIME type
  const fileDir = path.dirname(filePath);
  const fileName = path.basename(filePath);
  const thumbFilePath = path.normalize(path.join(fileDir, `${THUMB_PREFIX}${fileName}.png`));
  const tempLocalFile = path.join(os.tmpdir(), filePath);
  const tempLocalDir = path.dirname(tempLocalFile);
  const tempLocalThumbFile = path.join(os.tmpdir(), thumbFilePath);

  // Don't run when deleting files
  if (object.resourceState === 'not_exists') {
    console.log('Deleted file');
    return null;
  }

  // Check if it's a eps, ps or ai file before proceeding
  if (contentType != "application/postscript") {
    console.log("We don't need to transform this file");
    return null;
  }

  // Exit if the image is already a thumbnail.
  if (fileName.startsWith(THUMB_PREFIX)) {
    console.log('Already a Thumbnail.');
    return null;
  }

  // Cloud Storage files.
  const bucket = gcs.bucket(object.bucket);
  const file = bucket.file(filePath);
  const thumbFile = bucket.file(thumbFilePath);
  const metadata = {
    contentType: 'image/png',
    // To enable Client-side caching you can set the Cache-Control headers here. Uncomment below.
    // 'Cache-Control': 'public,max-age=3600',
  };

  // Create the temp directory where the storage file will be downloaded.
  return mkdirp(tempLocalDir).then(() => {
    // Download file from bucket.
    return file.download({ destination: tempLocalFile });
  }).then(() => {
    console.log("The file has been downloaded to", tempLocalFile);
    // Generate a thumbnail using ImageMagick.
    return spawn('convert', ['-colorspace', 'sRGB', '-density', '300', tempLocalFile, '-resize', '400x400', tempLocalThumbFile]);
  }).then(() => {
    console.log('Thumbnail created at', tempLocalThumbFile);
    // Uploading the Thumbnail.
    return bucket.upload(tempLocalThumbFile, { destination: thumbFilePath, metadata: metadata });
  }).then(() => {
    console.log('Thumbnail uploaded to Storage at', thumbFilePath);
    // Once the image has been uploaded delete the local files to free up disk space.
    fs.unlinkSync(tempLocalFile);
    fs.unlinkSync(tempLocalThumbFile);
    // Get the Signed URLs for the thumbnail and original image.
    const config = {
      action: 'read',
      expires: '03-01-2500',
    };
    return Promise.all([
      thumbFile.getSignedUrl(config)
    ]);
  }).then((results) => {
    const thumbResult = results[0];
    const thumbFileUrl = thumbResult[0];
    console.log('Got Signed URLs: ' + results);
    console.log('Thumb result:' + thumbResult);
    console.log('Thumb file URL: ' + thumbFileUrl);
    // Add the URLs to the Database
    return admin.firestore().doc(fileDir).update({ thumb_src: thumbFileUrl, processed: true }).then(() => {
      // write is complete here
      console.log("Thumbnail URLs saved to database.");
    });
  }).catch((error) => {
    console.error(error);
  });
});

Дайте мне знать, если мне нужно предоставить больше информации, но, как я уже сказал, код работает для некоторых файлов EPS. Сначала я подумал, что проблема может заключаться в размере входных файлов, и что преобразование не дожидается окончания загрузки - но я не уверен, так ли это.

...