将字节数组输出转换为 Blob 会损坏文件

2023-11-24

我正在使用 Office Javascript API 来使用 Angular 编写 Word 插件。

我想通过 API 检索 Word 文档,然后将其转换为文件并通过 POST 上传到服务器。

我使用的代码与 Microsoft 为此用例提供的文档代码几乎相同:https://dev.office.com/reference/add-ins/shared/document.getfileasync#example---get-a-document-in-office-open-xml-compressed-format

服务器端点要求通过多部分表单发布上传,因此我在创建 $http 调用时创建一个 FormData 对象,在该对象上附加文件(blob)以及一些元数据。

文件正在传输到服务器,但是当我打开它时,它已损坏,并且无法再用 Word 打开。

根据文档,Office.context.document.getFileAsync 函数返回一个字节数组。但是,生成的 fileContent 变量是一个字符串。当我 console.log 这个字符串时,它似乎是压缩数据,就像它应该的那样。

我的猜测是,在将字符串转换为 Blob 之前,我需要进行一些预处理。但是哪个预处理呢?通过 atob 进行 Base64 编码似乎没有做任何事情。

                let sendFile = ( fileContent ) => {

                    let blob = new Blob([fileContent], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' }),
                        fd = new FormData();

                    blob.lastModifiedDate = new Date();

                    fd.append('file', blob, 'uploaded_file_test403.docx');
                    fd.append('case_id', caseIdReducer.data());

                    $http.post('/file/create', fd, {
                        transformRequest: angular.identity,
                        headers: { 'Content-Type': undefined }
                    })
                    .success( ( ) => {

                        console.log('upload succeeded');

                    })
                    .error(( ) => {
                        console.log('upload failed');
                    });

                };


                function onGotAllSlices(docdataSlices) {

                    let docdata = [];

                    for (let i = 0; i < docdataSlices.length; i++) {
                        docdata = docdata.concat(docdataSlices[i]);
                    }

                    let fileContent = new String();

                    for (let j = 0; j < docdata.length; j++) {
                        fileContent += String.fromCharCode(docdata[j]);
                    }

                    // Now all the file content is stored in 'fileContent' variable,
                    // you can do something with it, such as print, fax...

                    sendFile(fileContent);

                }

                function getSliceAsync(file, nextSlice, sliceCount, gotAllSlices, docdataSlices, slicesReceived) {
                    file.getSliceAsync(nextSlice, (sliceResult) => {

                        if (sliceResult.status === 'succeeded') {
                            if (!gotAllSlices) { // Failed to get all slices, no need to continue.
                                return;
                            }

                            // Got one slice, store it in a temporary array.
                            // (Or you can do something else, such as
                            // send it to a third-party server.)
                            docdataSlices[sliceResult.value.index] = sliceResult.value.data;
                            if (++slicesReceived === sliceCount) {
                                // All slices have been received.
                                file.closeAsync();

                                onGotAllSlices(docdataSlices);

                            } else {
                                getSliceAsync(file, ++nextSlice, sliceCount, gotAllSlices, docdataSlices, slicesReceived);
                            }
                        } else {

                            gotAllSlices = false;
                            file.closeAsync();
                            console.log(`getSliceAsync Error: ${sliceResult.error.message}`);
                        }
                    });
                }

                // User clicks button to start document retrieval from Word and uploading to server process
                ctrl.handleClick = ( ) => {

                    Office.context.document.getFileAsync(Office.FileType.Compressed, { sliceSize: 65536 /*64 KB*/ }, 
                        (result) => {
                            if (result.status === 'succeeded') {

                                // If the getFileAsync call succeeded, then
                                // result.value will return a valid File Object.
                                let myFile = result.value,
                                    sliceCount = myFile.sliceCount,
                                    slicesReceived = 0, gotAllSlices = true, docdataSlices = [];

                                // Get the file slices.
                                getSliceAsync(myFile, 0, sliceCount, gotAllSlices, docdataSlices, slicesReceived);

                            } else {

                                console.log(`Error: ${result.error.message}`);

                            }
                        }
                    );
                };

我最终使用 fileContent 字符串执行此操作:

let bytes = new Uint8Array(fileContent.length);

for (let i = 0; i < bytes.length; i++) {
    bytes[i] = fileContent.charCodeAt(i);
}

然后我继续使用这些字节构建 Blob:

let blob = new Blob([bytes], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });

如果我随后通过 POST 请求发送此文件,则该文件不会被破坏并且可以由 Word 正确打开。

我仍然觉得这可以通过更少的麻烦/更少的步骤来实现。如果有人有更好的解决方案,我很有兴趣学习。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将字节数组输出转换为 Blob 会损坏文件 的相关文章

随机推荐

  • 在 Linux 上如何通过名称而不是 PID 来终止进程? [复制]

    这个问题在这里已经有答案了 有时 当我尝试启动 Firefox 时 它会显示 Firefox 进程已在运行 所以我必须这样做 jeremy jeremy desktop ps aux grep firefox jeremy 7451 25
  • 如何在 Perl 中构建独立于操作系统的文件路径(包括可选的 Windows 驱动器号)?

    我需要在 Perl 脚本内构建一个文件路径 我应该使用哪个路径分隔符来允许我的脚本在 Windows 和 Unix 上运行 请记住 Windows 需要驱动器号 你要文件 规格 s catpath catpath Takes volume
  • 用 Javascript 编写组合和排列计算器的最有效方法

    我有一个数学网站http finitehelp com教学生有限数学 我认为包含一个计算器会很酷 所以我制作了一个用于 Javascript 中的组合和排列的计算器 实时计算器位于http finitehelp com finite cal
  • pySpark forEachPartition - 代码在哪里执行

    我正在使用 2 3 版本的 pySpark 在我当前的开发系统中无法更新到 2 4 并且有以下关于对于每个分区 首先是一些背景信息 据我了解 pySpark UDFs强制 Python 代码在 Python 实例中的 Java 虚拟机 JV
  • Rails 中带有 jquery params 的 link_to

    我想在我的 Rails 应用程序中进行就地搜索 我使用了带有原型的button to remote 但现在我使用的是JQuery 所以我更改为link to 这是我的代码 我想将地址文本字段传递到我的控制器 但输出不是我所期望的 mycon
  • DataGridView设置行高不起作用

    尝试像这样设置 RowHeight 在代码中 dgvTruckAvail RowTemplate Height 48 不起作用 我还尝试设置我添加的每一列的高度 不起作用 这是网格属性 this dgvTruckAvail AllowUse
  • d3.js 使用多列从 csv 文件中过滤

    我想使用 csv 中的多个列值进行过滤 我首先想按城市过滤 然后按关键性列过滤 我想过滤重要性 高 中 低 如何使用 AND OR 进行过滤 City 和 Criticality 是复选框 根据我想要过滤相应 csv 列中的数据的选择 寻找
  • 如何在 32 位平台上调用 GetWindowLongPtr 和 SetWindowLongPtr?

    我想 P 调用获取窗口长指针 and 设置窗口长指针 并且我看到有关它们的相互矛盾的信息 有消息称 在 32 位平台上 GetWindowLongPtr 只是一个调用 GetWindowLong 的预处理器宏 并且 GetWindowLon
  • Java:如何设置 htmlunit

    我对 Java 是个菜鸟 但我想尝试一下 htmlunit 我使用 netbeans 作为 IDE 并创建了一个项目文件夹 hu1 以下是该文件夹的结构 hu1 gt nbproject gt src gt hu1 gt test 现在 我
  • 带有共享 ID 的 JPA @OneToOne —— 我可以做得更好吗?

    我正在使用一个我不想更改的现有架构 该架构在表 Person 和 VitalStats 之间具有一对一的关系 其中 Person 有一个主键 VitalStats 使用相同的字段作为 Person 的主键和外键 这意味着它的值是相应 PK
  • 如何处理 FirebaseAuthUserCollisionException

    我开始得到FirebaseAuthUserCollisionException当我尝试登录时出现异常Facebook in my Android应用 com google firebase auth FirebaseAuthUserColl
  • 如何将形状文件导入MySQL

    我需要将 shape 文件中的空间数据导入 MySQL 表中 我能够导入到 PostGreSQL 中 MySQL 的任何指针 我需要MySQL表中的数据 安装 FWtool 后尝试此操作 ogr2ogr f MySQL MySQL data
  • 为什么存在这些替代运算符表示

    考虑这些替代运算符表示 取自here Primary Alternative and and eq bitand bitor compl not not eq or or eq xor xor eq 为什么存在这些替代运算符表示 我喜欢它们
  • dplyr:在 mutate 命令中使用过滤器、group_by [重复]

    这个问题在这里已经有答案了 我想在数据表中添加一列 其中包含 y 的每个值除以 x 1 或 2 中相应条件的平均值 其中 x2 1 对于以下数据 其中 x 1 y 应除以 1 4其中 x 2 y 应除以 1 dt1 lt data tabl
  • Python:Rabin-Karp 算法哈希

    我为了好玩而实现 Rabin Karp 算法 我遇到了这个伪代码 RABIN KARP MATCHER T P d q 1 n T length 2 m P length 3 h d m 1 mod q 4 p 0 5 t 0 6 for
  • 测试rxjs的正确方法

    我把书带来了 rxjs 在行动 并完成测试部分 测试 rxjs 代码与通常的测试不同 因为一切都是延迟加载 在书中 他们提到了两种测试方法 要么传递完成 我正在使用 QUnit 完成信号异步代码已完成 要么传递大理石图 我的问题是 我应该选
  • 在 PHP Web 应用程序中使用时区

    我已经花了几个小时寻找在 PHP MySQL Web 应用程序中使用时区的最佳方法 但很难找到明确的答案 根据我到目前为止所学到的 最好将每个人的资料存储在 UTC 的数据库中 如果我错了 请纠正我 当用户注册时 我会询问他们所在的时区 然
  • 如何使用变量名称引用工作表上的控件对象?

    我已将列表框添加到工作表 而不是 用户表单 我用鼠标做到了这一点 我单击了小锤子和扳手图标 使用如下代码似乎可以轻松引用此列表框 ListBox1 Clear or ListBox1 AddItem An option 但是 我有三个这样的
  • 将活动标题椭圆设置为中间?

    我有一个活动 其标题不断变化 但有时它很长 最后会出现省略号 我可以将椭圆设置为中间吗 你可以这样做 final int actionBarTitle Resources getSystem getIdentifier action bar
  • 将字节数组输出转换为 Blob 会损坏文件

    我正在使用 Office Javascript API 来使用 Angular 编写 Word 插件 我想通过 API 检索 Word 文档 然后将其转换为文件并通过 POST 上传到服务器 我使用的代码与 Microsoft 为此用例提供