【发布时间】:2021-01-21 01:08:03
【问题描述】:
我有一个二进制文件(准确地说是 python pickle 文件)。每当请求这样的文件时,我都会在服务器端创建一个,然后通过flask 的send_file 将其作为AJAX 请求发送给客户端。
接下来,我需要将这个文件自动下载到客户端,所以我使用了this answer。
问题是,服务器上创建的文件通常大小为300 Bytes,而客户端下载的文件大小> 500 Bytes。另外,每当我尝试重用泡菜文件时,它都不会加载,并给出错误:
_pickle.UnpicklingError: invalid load key, '\xef'.
然而,服务器文件是无缝加载的。所以,问题是,客户端文件在传输过程中被损坏。我认为 js blob 可能是罪魁祸首。
有没有人见过这样的东西?
处理 AJAX(烧瓶)的服务器端代码
@app.route("/_exportTest",methods=['POST'])
def exportTest():
index = int(request.form['index'])
path = g.controller.exportTest(testID=index)
logger.debug("Test file path :"+path)
return send_file(path) #this is wrong somehow
关于exportTest函数:
def exportTest(self,testName):
dic = dict()
dic['screenShot'] = self.screenShot #string
dic['original_activity'] = self.original_activity #string
dic['steps'] = self.steps #list of tuples of strings
if self.exportFilePath=='.': #this is the case which will be true
filePath = os.path.join(os.getcwd(),testName)
else:
filePath = os.path.join(os.getcwd(),self.exportFilePath,testName)
logger.debug("filePath :"+filePath)
try:
pickle.dump(dic,open(filePath,"wb"),protocol=pickle.HIGHEST_PROTOCOL)
except Exception as e:
logger.debug("Error while pickling Test.\n Error :"+str(e)) #No such error was printed
return filePath
客户端代码:
$.ajax({
type: "POST",
// url: "/_exportTest",
url:"/_exportTest",
data:{index:testIndex},
success: function(response, status, xhr) {
// check for a filename
var filename = "TEST_"+testIndex+".tst";
var disposition = xhr.getResponseHeader('Content-Disposition');
if (disposition && disposition.indexOf('attachment') !== -1) {
var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
var matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
}
var type = xhr.getResponseHeader('Content-Type');
var blob = new Blob([response],{type:type});//, { type: type });
console.log("Binary type :"+type) ;
if (typeof window.navigator.msSaveBlob !== 'undefined') {
// IE workaround for "HTML7007: One or more blob URLs were revoked by closing the blob for which they were created. These URLs will no longer resolve as the data backing the URL has been freed."
console.log("WINDOW NAVIGATION MSSAVEBLOB type if undefined") ;
window.navigator.msSaveBlob(blob, filename);
}
else {
console.log("ELSE1")
var URL = window.URL || window.webkitURL;
var downloadUrl = URL.createObjectURL(blob);
if (filename) {
console.log("Filename exists") ;
// use HTML5 a[download] attribute to specify filename
var a = document.createElement("a");
// safari doesn't support this yet
if (typeof a.download === 'undefined') {
console.log("typeof a.download is undefined") ;
window.location.href = downloadUrl;
} else {
console.log("typeof a.download is not undefined") ;
a.href = downloadUrl;
a.download = filename;
document.body.appendChild(a);
a.click();
}
} else {
console.log("Filename does not exist") ;
window.location.href = downloadUrl;
}
// window.location.href = downloadUrl;
setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); // cleanup
}
}
});
【问题讨论】:
-
您的代码(客户端或服务器)可能有问题
-
所以这是正确的方法,对吧?处理二进制文件有什么特别的吗?
-
this is the correct way- 不确定this是什么,因为您没有显示任何代码 -
我已经从我链接的答案中复制了 blob 代码。如果需要任何其他代码 sn-ps,我将附上它们。请告诉我。
-
在客户端,您使用的是
XMLHttpRequest、jQuery.ajax还是其他一些包装器?还可以尝试在服务器端发送 mime 类型:send_file(path, 'application/octet-stream')。
标签: javascript python flask blob pickle