gpt4 book ai didi

javascript - 将 Excel 上传到 Google Cloud Storage 时出错

转载 作者:行者123 更新时间:2023-12-02 21:44:32 29 4
gpt4 key购买 nike

我正在使用“exceljs”库。它在我的本地节点服务器上运行得很好。现在,我尝试使用 Firebase Functions 将 Excel 文件上传到 Google Cloud 存储。

这是我正在使用的完整代码:

'use strict';
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const ExcelJS = require('exceljs');

admin.initializeApp();

var workbook = new ExcelJS.Workbook();
var worksheet = workbook.addWorksheet('Relatório Consolidado');



function startExcel(){

worksheet.columns = [
{ header: 'Empresa', key: 'empresa', width: 25 },
{ header: 'Data criação', key: 'data_criacao', width: 25 },
{ header: 'Responsável agendamento', key: 'agendador', width: 25 },
{ header: 'Colaborador', key: 'colaborador', width: 25 },
{ header: 'Endereço', key: 'endereco', width: 25 },
{ header: 'CPF', key: 'cpf', width: 25 },
{ header: 'CTPS', key: 'ctps', width: 25 },
{ header: 'Função', key: 'funcao', width: 25 },

{ header: 'Data agendado', key: 'nome_subtipo_produto', width: 25 },
{ header: 'Data atendimento médico', key: 'nome_subtipo_produto', width: 25 },
{ header: 'Data inicio atendimento', key: 'nome_subtipo_produto', width: 25 },
{ header: 'Data inicio exames', key: 'nome_subtipo_produto', width: 25 },
{ header: 'Tipo de exame', key: 'valor_produto', width: 25 },
{ header: 'Exames realizados', key: 'valor_produto', width: 25 },
{ header: 'Status atendimento', key: 'tipoPagamento', width: 25 },
{ header: 'Status exames', key: 'centroCustoStr', width: 25 }
];
}

function salvaExcel(){

return new Promise(function(resolve, reject){

let filename = `/tmp/Relatorio.xlsx`
let bucketName = 'gs://xxx.appspot.com/Relatorios'
const bucket = admin.storage().bucket(bucketName);

workbook.xlsx.writeFile(filename)
.then(() => {

console.log('Excel criado com sucesso! Enviando upload do arquivo: ' + filename)

const metadata = {
contentType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
};

bucket.upload(filename, metadata)

.then(() => {
const theFile = bucket.file(filename);
theFile.getSignedURL(signedUrlOptions)

.then((signedUrl) => {
resolve(signedUrl)
});

})
.catch((error) => {
reject('Erro ao realizar upload: ' + error)
})
})

.catch((error) => {
reject('Erro ao realizar upload: ' + error)
})

})
}

startExcel()


/**********************************
* Relatórios
********************************/

function relatorios(change, context){

return new Promise((resolve, reject) => {

const snapshot = change.after
const data = snapshot.val()

verificaRelatorioAgendamentos(change)

.then(() => {
resolve()

})

.catch((error => {
reject(error)

}))

})
}


function verificaRelatorioAgendamentos(change, context){

return new Promise((resolve, reject) => {

const snapshot = change.after
const data = snapshot.val()
const dataInicial = data.dataInicial
const year = moment(dataInicial).format('YYYY')
const month = moment(dataInicial).format('MM')
const state = 'DF'
let path = "/agendamentos/" + state + "/" + year + "/" + month

const relatorios = admin.database().ref(path).once('value');

return Promise.all([relatorios])

.then(results => {

let valores = results[0]
criaRelatorioAgendamentos(valores)

.then(() => {
resolve()

})

.catch((error => {
reject(error)

}))

})

})

}


function criaRelatorioAgendamentos(results){

return new Promise((resolve, reject) => {

let promises = []

results.forEach(element => {

let promise = new Promise(function(resolveExcel){

let data = element.val()

worksheet.addRow({
id: 1,
empresa: data.agendador.company,
data_criacao: data.dataCriacao,
agendador: data.agendador.nome,
colaborador: data.colaborador.nome,
cpf: data.colaborador.cpf,
ctps: data.colaborador.ctps,
funcao: data.colaborador.funcao,
data_agendado: data.data,
data_atendimento_medico: data.dataAtendimento,
data_inicio_atendimento: data.dataInicio,
data_inicio_exames: data.dataInicioExames,
tipo_exame: data.tipoExame,
exames: data.exames[0].nome,
status_atendimento: data.status,
status_exames: data.statusExames

})

resolveExcel()

})

promises.push(promise)

})

Promise.all(promises)

.then(() => {
salvaExcel()

.then((url) => {

console.log('Salvar URL' + url)

resolve(url)

})

.catch((error => {
reject(error)

}))


})


})

}


exports.relatorios = functions.database.ref('/relatorios/{state}/{year}/{month}/{relatoriosId}')
.onWrite((change, context) => {
return relatorios(change, context)
});

在函数控制台上,日志显示 Excel 文件已成功创建。但是上传的时候,出现了一个很奇怪的错误:

enter image description here

我做错了什么?我感谢任何帮助。

谢谢!

最佳答案

您收到的错误消息来自于尝试获取不存在文件的签名 URL。

当您调用 bucket.upload(filename,metadata) 时,您将上传文件 /tmp/Relatorio.xlsx,该文件会在您的存储桶中创建一个名为 Relatorio.xlsx。在下一行中,您调用 bucket.file(filename); ,它错误地将自身与 /tmp/Relatorio.xlsx 而不是 Relatorio.xlsx 关联起来.

要解决此问题,您应该使用从 bucket.upload() 解析的 File 对象,而不是自己创建它:

bucket.upload(filename, metadata)
.then((file) => file.getSignedURL())
.then((url) => {
console.log('Salvar URL' + url)
})

其他说明和修复

您的代码还包含许多不必要的 new Promise((resolve,reject) => { ... }) 调用。这称为 Promise 构造函数反模式,其中大多数可以通过正确链接 Promise 来删除。这个blog post是一个关于 Promise 以及如何正确使用它们的很好的速成类(class)。

关于函数的源代码,由于函数的 index.js 文件将包含多个函数定义,因此您不应在 index.js 的顶部定义变量文件,除非它们被所有函数共享,并且在多次调用函数的情况下它们是无状态的。在处理 I/O 或文件等内存密集型资源时,这一点尤其重要。

使用您当前的代码,如果在短时间内调用 relatorios 函数两次,则保存的文件将包含第一次调用的旧数据和当前调用的新数据,从而导致无效文件和潜在的错误。内存泄漏。

删除过多的 Promise 调用并使其能够重新运行您的 exceljs 代码,而不会损坏以下 index.js 文件中的任何数据结果:

'use strict';
const functions = require('firebase-functions');
const admin = require('firebase-admin');
// 'exceljs' is required on-demand in MyExcelSheetHelper

admin.initializeApp();

/* HELPER CLASS */

/**
* A helper class used to create reuseable functions that won't
* conflict with each other
*/
class MyExcelSheetHelper {

constructor() {
const ExcelJS = require('exceljs');

this.workbook = new ExcelJS.Workbook();
this.worksheet = this.workbook.addWorksheet('Relatório Consolidado');

this.worksheet.columns = [
{ header: 'Empresa', key: 'empresa', width: 25 },
{ header: 'Data criação', key: 'data_criacao', width: 25 },
{ header: 'Responsável agendamento', key: 'agendador', width: 25 },
{ header: 'Colaborador', key: 'colaborador', width: 25 },
{ header: 'Endereço', key: 'endereco', width: 25 },
{ header: 'CPF', key: 'cpf', width: 25 },
{ header: 'CTPS', key: 'ctps', width: 25 },
{ header: 'Função', key: 'funcao', width: 25 },

{ header: 'Data agendado', key: 'nome_subtipo_produto', width: 25 },
{ header: 'Data atendimento médico', key: 'nome_subtipo_produto', width: 25 },
{ header: 'Data inicio atendimento', key: 'nome_subtipo_produto', width: 25 },
{ header: 'Data inicio exames', key: 'nome_subtipo_produto', width: 25 },
{ header: 'Tipo de exame', key: 'valor_produto', width: 25 },
{ header: 'Exames realizados', key: 'valor_produto', width: 25 },
{ header: 'Status atendimento', key: 'tipoPagamento', width: 25 },
{ header: 'Status exames', key: 'centroCustoStr', width: 25 }
];
}

/**
* Streams this workbook to Cloud Storage
* @param storageFilepath - the relative path where the file is uploaded to Cloud Storage
* @returns the signed URL for the file
*/
salva(storageFilepath) {
if (!storageFilepath) {
return Promise.reject(new Error('storageFilepath is required'));
}

const bucket = admin.storage().bucket();

const storageFile = bucket.file(storageFilepath);

const uploadFilePromise = new Promise((resolve, reject) => {
try {
const stream = storageFile.createWriteStream({
contentType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
});

stream.on('finish', () => {
resolve();
});

stream.on('error', error => {
reject(error);
});

this.workbook.xlsx.write(stream)
.then(() => {
stream.end();
});

} catch (e) { // catches errors from createWriteStream
reject(e);
}
})

return uploadFilePromise
.then(() => {
var CONFIG = {
action: 'read',
expires: '03-01-2500',
};

bucket.file(storageFilepath).getSignedUrl(CONFIG)
.then((signedUrl) => {

return signedUrl
})
})

}
}

/* FUNCTIONS CODE */

function criaRelatorioAgendamentos(path, querySnapshot) {
const excelFileHelper = new MyExcelSheetHelper();
const worksheet = excelFile.worksheet;

// this forEach loop is synchronous, so no Promises are needed here
querySnapshot.forEach(entrySnapshot => {
const data = entrySnapshot.val();

worksheet.addRow({
id: 1,
empresa: data.agendador.company,
data_criacao: data.dataCriacao,
agendador: data.agendador.nome,
colaborador: data.colaborador.nome,
cpf: data.colaborador.cpf,
ctps: data.colaborador.ctps,
funcao: data.colaborador.funcao,
data_agendado: data.data,
data_atendimento_medico: data.dataAtendimento,
data_inicio_atendimento: data.dataInicio,
data_inicio_exames: data.dataInicioExames,
tipo_exame: data.tipoExame,
exames: data.exames[0].nome,
status_atendimento: data.status,
status_exames: data.statusExames
});
});

return excelFileHelper.salva(path + '/Relatorio.xlsx');
}

exports.relatorios = functions.database.ref('/relatorios/{state}/{year}/{month}/{relatoriosId}')
.onWrite((change, context) => {

// Verificar relatorio agendamentos

const snapshot = change.after;
const data = snapshot.val();
const dataInicial = data.dataInicial;
const year = moment(dataInicial).format('YYYY');
const month = moment(dataInicial).format('MM');
const state = 'DF';
const path = "/agendamentos/" + state + "/" + year + "/" + month;

return admin.database().ref(path).once('value')
.then(valores => {
return criaRelatorioAgendamentos(path, valores);
});
});

关于javascript - 将 Excel 上传到 Google Cloud Storage 时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60291181/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com