我的节点服务器从外部API获取文件的内容(base64字符串)。我希望内存中的base64字符串由客户端作为文件下载。但是,该文件在客户端的浏览器下载后已损坏。
如果我获取相同的文件内容,使用fs将其保存到服务器的本地文件夹,然后将该文件发送到客户端,则该文件将正确保存在客户端的系统上。
当我看一下这两组十六进制数据之间的区别时,有区别也有相似之处比较屏幕截图,有效文件在顶部
以前有人克服过这个问题吗?或者有一个理论可以解释为什么一个有效,另一个无效如果可能的话,我想尽量避免在服务器上保存文件的步骤
attachment.Name = 'picture.jpg'; //this can be any type of file
attachment.ContentType = 'image/jpeg'; //just an example with an image
attachment.ContentBytes = 'iVBORw0KGgoAAAAN.....' //long but complete base64 string
用于内存下载的代码(文件在客户端机器上损坏一次):
注意:以下变量contents
的十六进制表示与有效文件的十六进制数据相同
var atob = require('atob');
//tell the browser to download this
res.setHeader('Content-disposition', 'attachment; filename=' + attachment.Name);
res.setHeader('Content-type', attachment.ContentType);
var contents = atob(attachment.ContentBytes);
return res.send(200, contents);
还有
提供本地文件下载服务的代码(文件在客户端机器上有效一次):
var fs = require("fs");
var directory = "temporary/" + attachment.Name;
//tell the browser to download this
res.setHeader('Content-disposition', 'attachment; filename=' + attachment.Name);
res.setHeader('Content-type', attachment.ContentType);
//save the file on the server temporarily
fs.writeFile(directory, attachment.ContentBytes, 'base64', function(err)
{
if (err)
{
console.log(err);
return res.serverError();
}
});
//send the file to the client
var fileStream = fs.createReadStream(directory);
fileStream.pipe(res);
//once the file is sent, send 200 and delete the file from the server
fileStream.on('end', function ()
{
fs.unlink(directory);
return res.ok();
});
这解决了我的问题。发送到客户端的是一个适当字节的缓冲区,而不是ASCII字符串。浏览器似乎很乐意接受这一点。
//tell the browser to download this
res.setHeader('Content-disposition', 'attachment; filename=' + attachment.Name);
res.setHeader('Content-type', attachment.ContentType);
//convert to a buffer and send to client
var fileContents = new Buffer(attachment.ContentBytes, "base64");
return res.send(200, fileContents);