我正在努力实现以下目标,但是作为一个新手,我看不到自己在做什么错:
以下代码有效,但不一致:
在我的index.js文件中,我通过以下方式创建HTTP触发器:
export const image = functions.https.onRequest(uploadImage);
那叫:
import * as admin from "firebase-admin";
import * as Busboy from "busboy";
import * as fs from "fs";
import * as os from "os";
import * as path from "path";
const cors = require("cors")({ origin: true });
const spawn = require("child-process-promise").spawn;
const gcconfig = {
projectId: "PROJECT_ID",
keyFilename: "key.json"
};
const gcs = require("@google-cloud/storage")(gcconfig);
export const uploadImage = (req, res) => {
cors(req, res, () => {
if (req.method === "POST") {
const busboy = new Busboy({ headers: req.headers });
const docRef = req.query.docRef;
const fieldRef = req.query.fieldRef;
const storageRef = req.query.storageRef;
let fileData = null;
// Max height and width of the thumbnail in pixels.
const THUMB_MAX_HEIGHT = 100;
const THUMB_MAX_WIDTH = 100;
const THUMB_PREFIX = "thumb_";
const RESIZED_MAX_HEIGHT = 500;
const RESIZED_MAX_WIDTH = 500;
const RESIZED_PREFIX = "resized_";
const ORIGINAL_MAX_HEIGHT = 1000;
const ORIGINAL_MAX_WIDTH = 1400;
// Listen for event when Busboy finds a file to stream.
busboy.on("file", (fieldname, file, filename, encoding, mimetype) => {
const tempLocalFile = path.join(os.tmpdir(), filename);
fileData = { file: filename, type: mimetype };
// Download file local tmp.
file.pipe(fs.createWriteStream(tempLocalFile));
});
busboy.on("finish", () => {
// File and directory paths.
const tempLocalFile = path.join(os.tmpdir(), fileData.file);
const tempLocalThumbFile = path.join(os.tmpdir(),`${THUMB_PREFIX}${fileData.file}`);
const tempLocalResizedFile = path.join(os.tmpdir(),`${RESIZED_PREFIX}${fileData.file}`);
const origFilePath = path.normalize(path.join(storageRef, fileData.file));
const thumbFilePath = path.normalize(path.join(storageRef, `${THUMB_PREFIX}${fileData.file}`));
const resizedFilePath = path.normalize(path.join(storageRef, `${RESIZED_PREFIX}${fileData.file}`));
// Cloud Storage files.
const bucket = gcs.bucket("PROJECT_ID.appspot.com");
const metadata = {
contentType: fileData.type,
"Cache-Control": "public,max-age=3600"
};
// Generate a thumbnail called tempLocalThumbFile
const promise = spawn(
"convert",
[
tempLocalFile,
"-thumbnail",
`${THUMB_MAX_WIDTH}x${THUMB_MAX_HEIGHT}>`,
tempLocalThumbFile
],
{ capture: ["stdout", "stderr"] }
);
return promise
.then(() => {
// Generate a resized_ called tempLocalResizedFile
return spawn(
"convert",
[
tempLocalFile,
"-thumbnail",
`${RESIZED_MAX_WIDTH}x${RESIZED_MAX_HEIGHT}>`,
tempLocalResizedFile
],
{ capture: ["stdout", "stderr"] }
);
})
.then(() => {
// Resize original to ensure it's not massive
return spawn(
"convert",
[
tempLocalFile,
"-thumbnail",
`${ORIGINAL_MAX_WIDTH}x${ORIGINAL_MAX_HEIGHT}>`,
tempLocalFile
],
{ capture: ["stdout", "stderr"] }
);
})
.then(() => {
// upload images to storage
const thumbUp = bucket.upload(tempLocalThumbFile, {
destination: thumbFilePath,
metadata: metadata
});
const resizeUp = bucket.upload(tempLocalResizedFile, {
destination: resizedFilePath,
metadata: metadata
});
const origUp = bucket.upload(tempLocalFile, {
destination: origFilePath,
metadata: metadata
});
return Promise.all([thumbUp, resizeUp, origUp]);
})
.then(() => {
// Once the image has been uploaded delete the local files to free up disk space.
fs.unlinkSync(tempLocalFile);
fs.unlinkSync(tempLocalThumbFile);
fs.unlinkSync(tempLocalResizedFile);
const config = {
action: "read",
expires: "03-01-2500"
};
// Get the Signed URLs for the thumbnail and original image.
return Promise.all([
bucket.file(thumbFilePath).getSignedUrl(config),
bucket.file(resizedFilePath).getSignedUrl(config),
bucket.file(origFilePath).getSignedUrl(config)
]);
})
.then(results => {
console.log("Got Signed URLs.", results);
const thumbFileUrl = results[0][0];
const resizeFileUrl = results[1][0];
const origFileUrl = results[2][0];
// Add the URLs to the Database
return admin
.firestore()
.doc(docRef)
.update({
[fieldRef + ".original"]: origFileUrl,
[fieldRef + ".resized"]: resizeFileUrl,
[fieldRef + ".thumb"]: thumbFileUrl
});
})
.then(() => {
console.log("Image URLs saved to Firestore.");
res.status(200).send({
message: "File Saved."
});
})
.catch(err => {
console.log("Error:", err);
res.status(500).send({
error: err
});
});
});
busboy.end(req.rawBody);
} else {
return res.status(500).json({
message: "Not Allowed"
});
}
});
};
失败时收到的错误消息是:
错误:{ChildProcessError:
convert /tmp/ff658860-cc0f-11e8-bd7d-178b6a853dfe.png -thumbnail 100x100> /tmp/thumb_ff658860-cc0f-11e8-bd7d-178b6a853dfe.png
在ChildProcess上失败,代码为1。 (/user_code/node_modules/child-process-promise/lib/index.js:132:23)在也许关闭(内部)在ChildProcess.emit(events.js:191:7)上的generateTwo(events.js:106:13) /child_process.js:920:16)。 (internal / child_process.js:351:11)在Epi.One(events.js:96:13)在Socket.emit(events.js:188:7)在Pipe._handle.close [作为_onclose](net.js: 509:12)名称:“ ChildProcessError”,代码:1,childProcess:ChildProcess {域:域{域:null,_events:[Object],_eventsCount:1,_maxListeners:未定义,成员:[]},_events:{错误:[功能:t],关闭:[功能]},_eventsCount:2,_maxListeners:未定义,_closes需要:3,_closesGot:3,已连接:false,signalCode:null,exitCode:1,已杀死:false,spawnfile:'convert ',_handle:null,spawnargs:['convert','/tmp/ff658860-cc0f-11e8-bd7d-178b6a853dfe.png','-thumbnail','100x100>','/ tmp / thumb_ff658860-cc0f-11e8- bd7d-178b6a853dfe.png'],pid:12,标准输入:Socket {连接:false,_hadError:false,_handle:null,_parent:null,_host:null,_可读状态:[Object],可读性:false,域:[Object ],_ events:[Object],_ eventsCount:2,_maxListeners:未定义,_writableState:[Object],可写:false,allowHalfOpen:false ,已销毁:true,_bytes已调度:0,_sockname:null,_pendingData:null,_pendingEncoding:“”,服务器:null,_server:null,写入:[Function:writeAfterFIN],_ idleNext:null,_idlePrev:null,_idleTimeout:-1 },stdout:套接字{连接:false,_hadError:false,_handle:null,_parent:null,_host:null,_visibleState:[Object],可读性:false,域:[Object],_events:[Object],_eventsCount: 4,_maxListeners:未定义,_writableState:[对象],可写:false,allowHalfOpen:false,销毁:true,_bytesDispatched:0,_sockname:null,_pendingData:null,_pendingEncoding:'',服务器:null,_server:null,读取:[Function],_using:true,_idleNext:null,_idlePrev:null,_idleTimeout:-1,写:[Function:writeAfterFIN]},stderr:Socket {连接:false,_hadError:false,_handle:null,_parent:null ,_host:null,_visibleState:[Object],可读:false,域:[Object],_events:[Object],_eventsCount:4,_maxListeners:未定义,_writableState:[Object],wri表:false,allowHalfOpen:false,销毁:true,_bytes调度:0,_sockname:null,_pendingData:null,_pendingEncoding:'',服务器:null,_server:null,读取:[功能],_using:true,_idleNext:null ,_idlePrev:null,_idleTimeout:-1,写入:[Function:writeAfterFIN]},stdio:[[Object],[Object],[Object]]},stdout:”,stderr:'convert:不正确的图片标题{ {1}} / tmp / thumb_ff658860-cc0f-11e8-bd7d-178b6a853dfe.png \'@ error / convert.c / ConvertImageCommand / 3210。\ n'}
我对busboy并不熟悉,但是我相信我正确地结束了该过程,但是由于这通常仅适用于保存云功能后的首次上传,因此我怀疑代码可能不会干净地结束吗?
任何帮助将不胜感激。谢谢。