Versão atual:

Retorno da API createDocument - "ECMInsertDocumentException"

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.

Versão (1):

Ver a versão formatada

Retorno da API createDocument - "ECMInsertDocumentException"

Comentário

new question