Bom dia, estou tentando consumir a API:
ambientefluig.com/api/public/ecm/document/createDocument
Porém esporadicamente me deparo com o seguinte erro:
"{"content":"ERROR","message":{"message":"Arquivo Principal não encontrado /outsourcing/totvs/fluig-volume/data/upload/gustavo.maximo/arquivo pdf contendo espaços e acentuação no nome.pdf","detail":"Arquivo Principal não encontrado /outsourcing/totvs/fluig-volume/data/upload/gustavo.maximo/arquivo pdf contendo espaços e acentuação no nome.pdf","type":"ERROR","param":null,"errorCode":"ECMInsertDocumentException"}}"
Isso acontece aleatoriamente quando eu tento subir vários arquivos .pdf em fileira. Já com imagens isso não acontece, mesmo acima de 10mb e nomes com acentuação e espaços.
Ao testar durante horas, percebi um único padrão: ao subir 3 arquivos (qualquer tipo) com o mesmo nome em fileira a API retorna o erro acima.
Então eu desenvolvi um código que renomeia os arquivos antes de efetuar o upload e resolveu.
Entretanto com .pdfs em fileira, com uma chamada atrás da outra, o erro persiste (aleatoriamente, em apenas algumas chamadas, sem padrão aparente relacionado ao nome dos arquivos, talvez o conteúdo do arquivo influencie, não sei).
Código detalhado abaixo:
const uploadMultipleImages = async (files, table) => {
// Mostra loading
showLoading();
// Filtra nomes repetidos no fluig pois a saveDocumentAPI buga ao encontrar 3 nomes de arquivos repetidos
// Filtro de nomes start
// Pega todos os nomes que existem sem contar os repetidos
const namesWithoutDupes = [];
files.forEach((file) => {
if (!namesWithoutDupes.includes(file.name)) {
namesWithoutDupes.push(file.name);
}
});
// Array o qual não contem nomes duplicados, são todos marcados com 1, 2, 3... no final do nome para garantir que não hajam dupes
const filesWithNameDupePrevention = [];
namesWithoutDupes.forEach((nonRepeatedName) => {
let occurences = 0;
files.filter(e => e.name === nonRepeatedName).forEach((file) => {
occurences += 1;
if (occurences > 1) {
let newFileName = '';
const lastIndexOfDot = file.name.lastIndexOf('.');
if (lastIndexOfDot) {
newFileName = file.name.substr(0, lastIndexOfDot) + occurences + file.name.substr(lastIndexOfDot);
} else {
newFileName = file.name + occurences;
}
filesWithNameDupePrevention.push(new File([file], newFileName, { type: file.type }));
} else {
filesWithNameDupePrevention.push(new File([file], file.name, { type: file.type }));
}
});
});
// Filtro de nomes end
// Grava arquivo no GED e na tabela
await Promise.all(filesWithNameDupePrevention.map(async (file) => {
// Pensei que o problema fosse acentuação e caracteres especiais, logo
// utilizei encodeURI no nome do arquivo pra não dar pau na API, não deu certo
// const encodedFile = new File([file], encodeURI(file.name), { type: file.type });
// Upload no temp do fluig, necessário. (Equivalente a JQuery Fileupload pra quem é oldschool, shout out Caio Rodriguez)
const data = new FormData();
data.append('file', file);
await fetch('/ecm/upload', {
method: 'POST',
body: data,
}).catch(() => {
toast('Houve um erro ao criar o documento no GED. Contate o suporte da IV2 via suporte@iv2.com.br.', 'danger');
});
// Add linhas na tabela
const row = await addTableLine(table);
// Salva imagem no GED, retorna id e downloadURL
const idAndURL = await saveDocumentOnGED(file);
// Seta downloadURL, id, e nome do arquivo na tabela
const container = row.querySelector('.fileupload-container');
setImageDataOnTableRow(container, file.name, idAndURL);
})).then(() => {
arrangeTable(table);
hideLoading();
saveModalData();
});
};
No código acima, há 2 seções de importância:
- Upload no temp do fluig
- const idAndURL = await saveDocumentOnGED(file);
O primeiro item se refere ao upload na pasta temporária do fluig, faço com fetch ao invés do clássico JQuery Fileupload, funciona igual, não creio que seja o culpado pelo erro mas vale ressaltar.
O segundo item se refere a chamada da API de upload de documentos no GED, código abaixo:
const saveDocumentOnGED = (file => new Promise(async (resolve, reject) => {
// Salva doc/imagem no GED e salva a id do documento num campo
// pra poder deletar quando for substituido por outro doc/imagem
// Pega o id da pasta storage
const parentId = document.querySelector('#content').dataset.storageFolder;
// Objeto que incluirá id (GED) do novo doc/imagem e downloadURL
const returnObj = {};
// Salva documento no GED e retorna documentId dentro do documentData
saveDocumentAPI(file, parentId).then((documentData) => {
// Pega downloadURL através da api de pegar downloadURL
getDocumentDownloadURL(documentData.content.id).then((downloadURL) => {
returnObj.downloadURL = downloadURL.content;
returnObj.documentId = documentData.content.id;
resolve(returnObj);
}).catch((error) => {
toast('Houve um erro ao carregar a imagem. Contate o suporte da IV2 via suporte@iv2.com.br.', 'danger');
reject(error);
});
}).catch((error) => {
toast('Houve um erro ao salvar a imagem. Contate o suporte da IV2 via suporte@iv2.com.br.', 'danger');
reject(error);
});
}));
No código acima, preste atenção no saveDocumentAPI, é nessa hora que o código quebra, ao chamar a API. No retorno (documentData) vem o JSON citado no topo deste post.
Isso acontece as vezes, não consegui ver padrão.
Código da chamada da API (saveDocumentAPI):
const saveDocumentAPI = ((file, parentId) => new Promise((resolve, reject) => {
const documentPack = {
description: file.name,
parentId,
attachments: [{
fileName: file.name,
}],
};
fetch(window.location.origin + '/api/public/ecm/document/createDocument', {
method: 'POST',
redirect: 'follow',
headers: new Headers({
'Content-Type': 'application/json; charset=UTF-8',
}),
body: JSON.stringify(documentPack),
}).then(response => response.json()).then((data) => {
resolve(data);
}).catch((error) => {
reject(error);
});
}));
Screenshots do código rodando e do erro anexados ao post
Grato pela atenção. Qualquer ajuda é bem vinda.