从图库上传多张图片到rest方法导致一些图片没有上传

斯特凡诺·菲内蒂

编辑

所以我决定进一步研究这种情况。我试图链接各种函数返回的承诺,但到目前为止我没有运气。

我的应用程序的这一部分旨在不完全异步地工作,这就是现在引起巨大头痛的原因。

首先:Imagepicker 本身返回一个承诺。在这个承诺中,我拥有用户从图库中选择的所有图片 - 我已将限制设置为 5,但这无关紧要。

            this.imagePicker.getPictures(this.options)
            // Prima promise, ottengo le foto scelte dalla gallery
            .then((res) => {
                var count = 1;
                for (var i = 0; i < res.length; i++) {


                    var total = res.length;
                    let path:string = res[i].toString();
                    // Estraggo il nome e il percorso del file
                    var currentName = path.substr(path.lastIndexOf('/') + 1);
                    var correctPath = path.substr(0, path.lastIndexOf('/') + 1);

     })

现在,如果我正在使用除 typescript/javascript 之外的任何其他语言,我会在 for 循环内调用上传方法,每个文件一个,获取该特定文件的结果并调用将完成的第二个上传方法(元数据)上传并移动到 for 循环中的下一个文件。

但我不会使用任何其他语言,所以最初我想:“嘿,让我们将承诺嵌套起来!”。哪个有效,几乎完美无缺,直到您开始遇到一些网络问题,然后砰的一声,您永远不知道哪些文件被上传,哪些文件直到最后才上传。

问题是我如何链接来自不同功能的承诺?

我是这样试的(上面的代码现在如下图)

            this.imagePicker.getPictures(this.options)
            // Prima promise, ottengo le foto scelte dalla gallery
            .then((res) => {
                var count = 1;
                for (var i = 0; i < res.length; i++) {


                    var total = res.length;
                    let path:string = res[i].toString();
                    // Estraggo il nome e il percorso del file
                    var currentName = path.substr(path.lastIndexOf('/') + 1);
                    var correctPath = path.substr(0, path.lastIndexOf('/') + 1);

                this.file.readAsArrayBuffer(correctPath.toString(), currentName)
                    .then( result => {

                        let blob = new Blob([result], {type: "image/jpeg"});
                        return blob;
                    })
                }

     })

但是话又说回来,如果我想使用那个“blob”,我必须在那个承诺中链接一个 .then ,所以无论如何我最终都会嵌套它们。更糟糕的是,我现在知道一些代码将在承诺返回结果之前执行。而这正是发生的事情。循环继续进行,因为在调用 this.file.readAsArrayBuffer 之后,代码会跳转并关闭 for 循环迭代,同时等待 promise 实现,同时循环的第二次迭代会触发一个新的 promise。

上面经过编辑的代码片段和下面的原始代码都无法正确显示所显示的加载控制器,但它在真正开始下载之前就消失了,或者,如果我删除持续时间选项并放置一个 this.loadingController。在上传承诺的.then 部分中使用dismiss(),最后一个loadingController 永远保持开启状态,它永远不会被解除。

这是原始代码(在找到可行的解决方案之前,我仍然使用它)。

要求回顾: - 用户从图库中最多选择 5 张图片 - 5 张图片中的每一张都使用合适的加载控制器模式一次上传一次,直到上传结束,然后相应的元数据也被上传。- 在下载结束时会显示 Toast 向用户提供反馈 - 从下一个文件重新开始

在这种特殊情况下,我对用户在上传时可以做其他事情不感兴趣:我希望他们“卡住”加载直到结束。

原代码如下:

照片选择器 ()


        photoPicker() {

            if (!this.uploadForm.invalid) {
                this.options = {
                    width: 4000,
                    quality: 100,
                    outputType: 0,
                }

                this.imagePicker.getPictures(this.options)
                .then((res) => {
                    var count = 1;
                    for (var i = 0; i < res.length; i++) {

                        var total = res.length;
                        let path:string = res[i].toString();

                        // Estraggo il nome e il percorso del file
                        var currentName = path.substr(path.lastIndexOf('/') + 1);
                        var correctPath = path.substr(0, path.lastIndexOf('/') + 1);

                        if ( CONFIG.DEV == 1) { 
                            let datetime = new Date();
                            console.log('[objects-docs-multiupload] @ ' + datetime.toISOString() + ' picture path: ');
                            console.log(path);

                        }
                        // Leggo il contenuto in un buffer
                        this.file.readAsArrayBuffer(correctPath.toString(), currentName)
                        .then( result => {


                            if ( CONFIG.DEV == 1) { 
                                let datetime = new Date();
                                console.log('[objects-docs-multiupload] @ ' + datetime.toISOString() + 'data result: ');
                                console.log(result); 
                            }
                            // E uso il contenuto per creare un blob con il binario del file
                            let blob = new Blob([result], {type: "image/jpeg"});
                            if ( CONFIG.DEV == 1) { 
                                let datetime = new Date();
                                console.log('[objects-docs-multiupload] @ ' + datetime.toISOString() + 'data blob: ');
                                console.log(blob);
                            }
                            // invoco il metodo per caricare il file
                            this.uploadFile(blob, currentName, count, total);
                            count = count + 1;
                        });
                    }
                }, (err) => {
                    alert(err);
                });

            } else {

                this.showToastAlert('Compilare i dati del documento', 'error');
                return;
            }

            if (this.uploadForm.controls.recipient.value != '') {

                this.createTask();
            } 
            this.router.navigateByUrl('/objects-dashboard/'+this.obj_id);

        }

上传文件()


        async uploadFile(file, fileName, counter, total) {

            // Chiamo la funzione asincrona per la mascherina di caricamento
            // in modo da dare visibilità al fatto che la app è ferma per fare un upload
            this.presentUpLoading(counter, total);

            // Contatto il metodo uploadFile del rest
            this.restProvider.uploadFile(file, fileName)
            .then(data => {
                if ( CONFIG.DEV == 1) { 
                    let datetime = new Date();
                    console.log('[objects-dashboard] @ ' + datetime.toISOString() + 'response from uploadFile: ');
                    console.log(data);
                }
                // Qui devo fare un piccolo trucco
                // devo ritrasformare in json e quindi rifare il parse
                // per otternere un oggetto (recryptData) da usare per assemblare
                // l'url cui fare il redirect
                let decryptedData = JSON.stringify(data);
                let recryptData = JSON.parse(decryptedData);
                this.loadDoc(recryptData.uuid, recryptData.uploadName, counter, total);

            }); 
        }

加载文档()


        async loadDoc(uuid, uploadName, counter, total) {

            let upload = {
                name: this.uploadForm.controls.name.value+'_'+counter,
                categoryId: this.uploadForm.controls.cat_id.value.substring(3),
                description: this.uploadForm.controls.description.value+'_'+counter,
                filename: uploadName,
                uuid: uuid,
                objectId: this.obj_id,
            };
            if(CONFIG.DEV ==1) { console.log(upload); };
            this.restProvider.uploadDoc(upload)
            .then( data => {

                if (data['Result'] == 'Success') {

                    // OK: Richiamo la funzione showToastAlert
                    // per mostrare l'avviso Toast
                    this.showToastAlert('Documento Caricato '+counter+' di '+total, 'success');
                    // Rimando alla pagina messages-dashboard
                    //this.router.navigateByUrl('/objects-dashboard/'+this.obj_id);             

                } else {

                    // KO: Richiamo la funzione showToastAlert
                    // per mostrare l'avviso Toast
                    this.showToastAlert('Documento NON caricato '+counter+' di '+total, 'error');               
                }

            });
        }

斯特凡诺·菲内蒂

我终于设法让整个事情正常工作。事实证明,我以错误的方式调用了这些函数。我以正确的方式使用 await/async 解决了这个问题。

for..loop 的内部:

            this.imagePicker.getPictures(this.options)
            // Prima promise, ottengo le foto scelte dalla gallery
            .then(async (res) => {
                var count = 1;
                for (var i = 0; i < res.length; i++) {

                    var total = res.length;

                    let path:string = res[i].toString();
                    // Estraggo il nome e il percorso del file
                    var currentName = path.substr(path.lastIndexOf('/') + 1);
                    var correctPath = path.substr(0, path.lastIndexOf('/') + 1);

                    // Leggo il contenuto in un buffer
                    await this.file.readAsArrayBuffer(correctPath.toString(), currentName)
                    .then( (result) => {
                        // E uso il contenuto per creare un blob con il binario del file
                        this.blob = new Blob([result], {type: "image/jpeg"});
                        return this.blob;
                    })

                    // Visualizzo il loading controller che indica il caricamento in corso
                    if ( CONFIG.DEV == 1 ) console.log("Presenting loading controller for counter "+count+" of "+total);
                    this.presentUpLoading(count, total);
                    // Inizio l'upload del file col metodo rest e aspetto l'esito
                    if ( CONFIG.DEV == 1 ) console.log("Starting upload of "+currentName);
                    await this.uploadFile(this.blob, currentName,count, total);
                    if ( CONFIG.DEV == 1 ) console.log("RecryptData: ");
                    if ( CONFIG.DEV == 1 ) console.log(this.recryptData);
                    if ( CONFIG.DEV == 1 ) console.log("Loading Doc Metadata");
                    // Carico i metadati dei files e aspetto l'esito
                    await this.loadDoc(this.recryptData.uuid, this.recryptData.uploadName, count, total);
                    if ( CONFIG.DEV == 1 ) console.log("Dismissing loading controller");
                    // Elimino il loading controller e passo al successivo upload
                    this.dismissUpLoading();
                    if ( CONFIG.DEV == 1 ) console.log("incrementing counter");
                    count++;
                }
            })

这个技巧是让 getPictures 的 promise 结果成为一个异步函数,这样我就可以在我必须在循环中运行的所有其他 promise 中使用 await。通过这种方式,所有的承诺都在下一次执行循环之前得到履行,而且我还能够修复 loadingController,它现在在整个上传时间都保持打开状态。

为了让实际的上传函数与 await 一起工作,我必须将该函数的结果转换为 Promise 本身:

    uploadFile(file, fileName, counter, total) {

        // Chiamo la funzione asincrona per la mascherina di caricamento
        // in modo da dare visibilità al fatto che la app è ferma per fare un upload
        return new Promise((resolve) => {
            // Contatto il metodo uploadFile del rest
                this.restProvider.uploadFile(file, fileName)
                .then((data) => {
                    // Qui devo fare un piccolo trucco
                    // devo ritrasformare in json e quindi rifare il parse
                    // per otternere un oggetto (recryptData) da usare per assemblare
                    // l'url cui fare il redirect
                    let decryptedData = JSON.stringify(data);
                    this.recryptData = JSON.parse(decryptedData);
                    //this.loadDoc(this.recryptData.uuid, this.recryptData.uploadName, counter, total);
                    resolve(this.recryptData);
                }); 
        });
    }

多亏了这一点,数组“recryptData”可用于下一个函数(loadDoc),并且我能够避免承诺嵌套。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

使用PHP上传多张图片

来自分类Dev

没有指令的AngularJS图片上传预览

来自分类Dev

从Share Extension上传多张图片

来自分类Dev

Laravel使用Ajax上传多张图片

来自分类Dev

在一个请求中上传多张图片

来自分类Dev

凌空上传多张图片?

来自分类Dev

使用Node.js上传多张图片

来自分类Dev

上传图片到FTP

来自分类Dev

dropzone不上传一些图片(内部服务器错误500)

来自分类Dev

多张图片上传出现问题

来自分类Dev

如何使用Django Rest框架上传多张图片?

来自分类Dev

在上传之前预览多张图片

来自分类Dev

在上传多张图片之前预览图片

来自分类Dev

在单个发布请求中上传图片和其他一些参数

来自分类Dev

上传并显示一种产品的多张图片?

来自分类Dev

上传后的图片没有相等的空间

来自分类Dev

上传多张图片

来自分类Dev

用回形针上传多张图片?

来自分类Dev

使用Django上传多张图片

来自分类Dev

在wordpress中上传多张图片

来自分类Dev

解析Javascript-使用其他一些参数上传图片

来自分类Dev

在Codeigniter中上传多张图片?

来自分类Dev

每个对象上传多张图片

来自分类Dev

正确上传/下载多张图片?

来自分类Dev

用户上传图片到网站,然后在图库中显示

来自分类Dev

为什么我上传了一些图片,结果只上传了一张图片

来自分类Dev

Django多张图片没有上传

来自分类Dev

姜戈;上传一些图片的最佳方式是什么?

来自分类Dev

上传多张图片时只保存一张图片