- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在开发 Node Azure Function(在 Linux 上)来动态创建 GIF 图像。它在我的本地 MacBook 上运行得非常好,但当我部署到 Azure 时却失败了。
当查看日志时,我只是看到它在部署到 Azure 时在日志中抛出 Microsoft.Azure.WebJobs.Script.Workers.Rpc.RpcException
。
下面是我正在进行的代码。我已经包含了完整的功能代码,因为(对我来说)没有明显的错误源指示。有谁知道可能导致此问题的原因吗?
import { AzureFunction, Context, HttpRequest } from "@azure/functions"
import { DateTime, Duration } from "luxon";
import { Canvas } from "canvas";
import * as fs from 'fs';
const os = require('os');
const { GifEncoder } = require("@skyra/gifenc")
const { buffer } = require('node:stream/consumers');
const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
try {
let countdownTo: string = req.query.countdownTo || DateTime.now().plus({days: 7}).toFormat("yyyy-LL-dd'T'T");
let width: number = parseInt(req.query.width) || 300;
let height: number = parseInt(req.query.height);
let frames: number = parseInt(req.query.frames) || 180;
let background: string = '#' + (req.query.background || '000e4e');
let foreground: string = '#' + (req.query.foreground || '00b7f1');
// Set height to 1/3 width if not specified
if (!height) {
height = width/3;
}
// ========================================================================
// Set upper and lower limits
width = Math.max(width, Math.min(120, 640));
height = Math.max(height, Math.min(120, 640));
frames = Math.max(frames, Math.min(1, 600));
// Time calculations
const nowDate: DateTime = DateTime.now()
const targetDate: DateTime = DateTime.fromISO(countdownTo); // "2022-11-01T12:00"
let timeDifference: Duration = targetDate.diff(nowDate);
// ========================================================================
const encoder: any = new GifEncoder(width, height);
const canvas: Canvas = new Canvas(width, height);
const ctx: any = canvas.getContext('2d');
let fileName = targetDate.toFormat('yyyyLLddHHmmss') + '-' + nowDate.toFormat('yyyyLLddHHmmss') + '.gif';
// Specify temporary directory and create if it doesn't exist
const temporaryFileDirectory: string = os.tmpdir() + '/tmp/';
if (!fs.existsSync(temporaryFileDirectory)) {
fs.mkdirSync(temporaryFileDirectory);
}
// Stream the GIF data into a file
let filePath: string = temporaryFileDirectory + fileName + '.gif';
const readStream = encoder.createReadStream()
readStream.pipe(fs.createWriteStream(filePath));
// Set the font size, style, and alignment
let fontSize: string = Math.floor(width/12) + 'px';
let fontFamily: string = 'Arial';
ctx.font = [fontSize, fontFamily].join(' ');
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
// Start Encoding GIF
encoder.setRepeat(0).setDelay(1000).setQuality(10).start();
if (timeDifference.milliseconds <= 0) { // Date has passed
context.log('EXPIRED Date:', countdownTo);
// Set Canvas background color
ctx.fillStyle = background;
ctx.fillRect(0, 0, width, height);
// Print Text
ctx.fillStyle = foreground;
ctx.fillText('Date has passed!', (width/2), (height/2));
// Add frame to the GIF
encoder.addFrame(ctx);
}
else { // Date is in the future
timeDifference = targetDate.diff(DateTime.now(), ['days', 'hours', 'minutes', 'seconds']);
context.log('Date:', countdownTo);
for (let i: number = 0; i < frames; i++) {
// Extract the duration from the days
let days: number = Math.floor(timeDifference.days);
let hours: number = Math.floor(timeDifference.hours);
let minutes: number = Math.floor(timeDifference.minutes);
let seconds: number = Math.floor(timeDifference.seconds);
let daysDisplay: any = (days.toString().length == 1) ? '0' + days : days;
let hoursDisplay: any = (hours.toString().length == 1) ? '0' + hours : hours;
let minutesDisplay: any = (minutes.toString().length == 1) ? '0' + minutes : minutes;
let secondsDisplay: any = (seconds.toString().length == 1) ? '0' + seconds : seconds;
// Create the text to be displayed
let displayText: string = [daysDisplay, 'd ', hoursDisplay, 'h ', minutesDisplay, 'm ', secondsDisplay, 's'].join('');
//context.log(displayText);
// Set Canvas background color
ctx.fillStyle = background;
ctx.fillRect(0, 0, width, height);
// Print Text
ctx.fillStyle = foreground;
ctx.fillText(displayText, (width/2), (height/2));
// Add frame to the GIF
encoder.addFrame(ctx);
// Remove a second in preparation for the next frame
if (seconds < 1) {
if (minutes < 1) {
if (hours < 1) {
timeDifference = timeDifference.minus({days: 1});
}
timeDifference = timeDifference.minus({hours: 1});
}
timeDifference = timeDifference.minus({minutes: 1});
timeDifference = timeDifference.plus({seconds: 59});
}
else {
timeDifference = timeDifference.minus({seconds: 1});
}
}
}
// Encoding complete...
encoder.finish();
const fileData = await buffer(readStream);
//context.log(fileData);
context.res = {
headers: {
"Content-Type": "image/gif"
},
isRaw: true,
status: 200,
body: new Uint8Array(fileData)
};
fs.unlinkSync(filePath)
}
catch(ex: any) {
context.res = {
status: 200,
body: ex.message
};
}
};
export default httpTrigger;
最佳答案
我发现此问题与 Azure DevOps 管道的问题有关。管道表明它已成功运行,但它从未安装任何node_modules。
部署后,Function App 上的 node_modules 文件夹为空,导致对 Luxon 等内容的引用完全失败。
我切换到了 Github Actions,它运行良好,所以显然管道中的某些步骤不正确。
如果您遇到某个特定功能在本地完美运行但在生产中无法正常运行的问题,请仔细检查以确保您的 CI/CD 管道正常运行。
关于node.js - Node Azure 功能在本地运行,但在 Azure 中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74318614/
今天有小伙伴给我留言问到,try{...}catch(){...}是什么意思?它用来干什么? 简单的说 他们是用来捕获异常的 下面我们通过一个例子来详细讲解下
我正在努力提高网站的可访问性,但我不知道如何在页脚中标记社交媒体链接列表。这些链接指向我在 facecook、twitter 等上的帐户。我不想用 role="navigation" 标记这些链接,因
说现在是 6 点,我有一个 Timer 并在 10 点安排了一个 TimerTask。之后,System DateTime 被其他服务(例如 ntp)调整为 9 点钟。我仍然希望我的 TimerTas
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我就废话不多说了,大家还是直接看代码吧~ ? 1
Maven系列1 1.什么是Maven? Maven是一个项目管理工具,它包含了一个对象模型。一组标准集合,一个依赖管理系统。和用来运行定义在生命周期阶段中插件目标和逻辑。 核心功能 Mav
我是一名优秀的程序员,十分优秀!