Javascript 将字节数组输出转换为Blob会损坏文件
我正在使用Office Javascript API使用Angular为Word编写外接程序 我想通过API检索Word文档,然后将其转换为文件并通过POST将其上载到服务器 我使用的代码与Microsoft为此用例提供的文档代码几乎相同: 服务器端点要求通过多部分表单发布上传,因此在创建$http调用时,我创建了一个FormData对象,在该对象上附加了文件(blob)和一些元数据 该文件正在传输到服务器,但当我打开它时,它已损坏,无法再通过Word打开 根据文档,Office.context.document.getFileAsync函数返回一个字节数组。但是,生成的fileContent变量是一个字符串。当我输入console.log这个字符串时,它似乎是压缩数据,就像它应该是的一样 我的猜测是,在将字符串转换为Blob之前,我需要进行一些预处理。但是哪种预处理?通过atob进行Base64编码似乎没有任何作用Javascript 将字节数组输出转换为Blob会损坏文件,javascript,angularjs,api,ms-word,ms-office,Javascript,Angularjs,Api,Ms Word,Ms Office,我正在使用Office Javascript API使用Angular为Word编写外接程序 我想通过API检索Word文档,然后将其转换为文件并通过POST将其上载到服务器 我使用的代码与Microsoft为此用例提供的文档代码几乎相同: 服务器端点要求通过多部分表单发布上传,因此在创建$http调用时,我创建了一个FormData对象,在该对象上附加了文件(blob)和一些元数据 该文件正在传输到服务器,但当我打开它时,它已损坏,无法再通过Word打开 根据文档,Office.context
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}`);
}
}
);
};
let sendFile=(fileContent)=>{
设blob=newblob([fileContent],{type:'application/vnd.openxmlformats officedocument.wordprocessingml.document'}),
fd=新FormData();
blob.lastModifiedDate=新日期();
append('file',blob,'upload_file_test403.docx');
fd.append('case_id',caseIdReducer.data());
$http.post('/file/create',fd{
请求:angular.identity,
标题:{“内容类型”:未定义}
})
.成功(()=>{
console.log('upload successed');
})
.错误(()=>{
console.log('upload failed');
});
};
总切片上的函数(docdataSlices){
让docdata=[];
for(设i=0;i{
如果(sliceResult.status===“成功”){
如果(!gotAllSlices){//未能获取所有切片,则无需继续。
返回;
}
//得到一个切片,将其存储在临时数组中。
//(或者你可以做其他事情,比如
//将其发送到第三方服务器。)
docdataSlices[sliceResult.value.index]=sliceResult.value.data;
如果(++切片接收===切片计数){
//所有切片均已收到。
closeAsync()文件;
总切片(docdataSlices);
}否则{
getSliceAsync(文件、++nextSlice、sliceCount、GotalSlices、docdataSlices、slicesReceived);
}
}否则{
gotallsices=false;
closeAsync()文件;
log(`getSliceAsync Error:${sliceResult.Error.message}`);
}
});
}
//用户单击按钮开始从Word检索文档并上载到服务器进程
ctrl.handleClick=()=>{
Office.context.document.getFileAsync(Office.FileType.Compressed,{sliceSize:65536/*64 KB*/},
(结果)=>{
如果(result.status===“成功”){
//如果getFileAsync调用成功,则
//result.value将返回有效的文件对象。
让myFile=result.value,
sliceCount=myFile.sliceCount,
slicesReceived=0,gotAllSlices=true,docdataSlices=[];
//获取文件切片。
getSliceAsync(myFile、0、sliceCount、gotAllSlices、docdataSlices、slicesReceived);
}否则{
log(`Error:${result.Error.message}`);
}
}
);
};
Pff!获取文件实例而不使用FileReader api有什么问题?来吧,微软
您应该将字节数组放入blob构造函数,在javascript中将二进制blob转换为字符串是一个坏主意,可能会导致“超出范围”错误或编码错误
就这样做吧
var byteArray = new Uint8Array(3)
byteArray[0] = 97
byteArray[1] = 98
byteArray[2] = 99
new Blob([byteArray])
如果区块是一个或一个blob/file实例。在这种情况下,您只需执行以下操作:
blob = new Blob([blob, chunk])
请。。。不要对它进行base64编码(~3倍大+更慢)我最后用fileContent字符串完成了这项工作:
let bytes = new Uint8Array(fileContent.length);
for (let i = 0; i < bytes.length; i++) {
bytes[i] = fileContent.charCodeAt(i);
}
如果我通过POST请求发送此文件,则文件不会损坏,可以通过Word正确打开。let blob = new Blob([bytes], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
let bytes = new Uint8Array(docdata.length);
for (var i = 0; i < docdata.length; i++) {
bytes[i] = docdata[i];
}