保存BLOB(可能是数据!)通过AJAX调用的Azure Blob存储返回创建损坏图像 [英] Saving blob (might be data!) returned by AJAX call to Azure Blob Storage creates corrupt image
问题描述
如果我发布一个PDF给我的供应商API,他们回到我.png文件作为BLOB(参见更新2,因为我现在不能确定,如果他们返回blob数据)。
我想推到这一点的Azure Blob存储。用我下面列出code,它推动的东西,但该文件已损坏。例:从下载的Azure Blob存储的巴纽,并试图用画图打开它提供了以下错误:
这不是有效的位图文件,或它的格式是目前不 支持的。
我已经验证的图像发送给我正确的供应商能够打开巴纽站在他们一边。我想知道如果我需要把它上传到Azure的Blob存储前将其转换为一个base64或将其保存到本地网络目录。
下面是我的角前端控制器,叫我的节点/ EX preSS后台上传到Azure一旦接收到返回的形象:
$。阿贾克斯({
网址:'http://myvendorsapi.net/uploadPDF,
键入:POST,
数据:FORMDATA,
MIMETYPE:多部分/表单数据,
过程数据:假的,
的contentType:假的,
跨域:真正的,
成功:函数(结果){
VAR容器名称='container1';
VAR文件名='Texture_0.png';
var文件=结果;
$ http.post('/ postAdvanced',{容器名称:容器名称,文件名:文件名,文件:文件})。成功(功能(数据){
的console.log(成功!);
},功能(错误){
//console.log(err);
});
},
错误:功能(错误){
的console.log(出事了!);
}
})
}
下面是我的节点/ EX preSS后端即上传的blob的Azure Blob存储。它给没有错误,但该文件无法打开/给出了上述的错误,当画图中打开:
app.post('/ postAdvanced',功能(REQ,水库,下一个){
VAR容器名称= req.body.containerName;
VAR文件名= req.body.filename;
var文件= req.body.file;
blobSvc.createBlockBlobFromText(容器名称,文件名,文件,功能(错误,结果,响应){
如果(!错误){
res.send(结果);
}
其他 {
执行console.log(错误);
}
});
})
更新1:这里提供的答案让我通过在一些终端厂商的API的网址:<一href="http://stackoverflow.com/questions/32619369/download-file-via-webservice-and-push-it-to-azure-blob-storage-via-node-ex$p$pss">Download通过WebService的文件,并通过节点/ EX preSS 它推到的Azure Blob存储
它的工作原理,因为它写到文件中的端点到一个临时文件夹。在我目前的情况,我上传的PDF文件,并返回我需要上传到Azure的Blob存储的图像文件。有没有办法在这里使用的答案,但调整它,我已经有一个文件(因为它退还给我)与文件从URL流?
更新2:在控制台登录返回的文件,它看起来像它可能是数据。我不知道,它看起来是这样的:
这是实际的数据,如果是这样,我怎么使它成为了上传图片?
更新3:
由于看来jQuery的AJAX不能管理二进制的回报。我能够使用XMLHTT presponse如下,以开放的斑点,但我似乎不能推到这一点的Azure,因为它给了我下面的错误:
类型错误:必须从数量,缓存,阵列或字符串
下面是我的要求。请注意,文件打开正常:
变种形式= document.forms.namedItem(FileInfo的);
form.addEventListener('提交',函数(EV){
VAR ODATA =新FORMDATA(表);
VAR XHR =新XMLHtt prequest();
xhr.responseType =arraybuffer;
xhr.open(POST,HTTP:// myvendorsapi /上传,真正的);
xhr.onload =功能(oEvent){
如果(xhr.status == 200){
VAR BLOB =新的斑点([xhr.response] {类型:图像/ PNG});
VAR的ObjectURL = URL.createObjectURL(BLOB);
的window.open(的ObjectURL);
执行console.log(BLOB);
VAR容器名称= boxContainerName;
VAR文件名='Texture_0.png';
$ http.post('/ postAdvanced',{容器名称:容器名称,文件名:文件名,文件:BLOB})。成功(功能(数据){
//console.log(data);
的console.log(成功!);
},功能(错误){
//console.log(err);
});
} 其他 {
oOutput.innerHTML =错误+ xhr.status +当试图上传文件&LT发生; BR \ /&gt;中;
}
};
xhr.send(ODATA);
。EV preventDefault();
}, 假);
createBlockBlobFromText将与字符串或缓冲区。您可能需要一个缓冲区来存放二进制内容由于已知问题的jQuery。
有关解决方法,有几种选择:
选项1: 读二进制filesusing jQuery的AJAX
选项2: <一个href="http://stackoverflow.com/questions/17657184/using-jquerys-ajax-method-to-retrieve-images-as-a-blob">Use本地XMLHtt prequest
选项3:写前端与节点以及与 browserify 它。 您的前端code可能看起来像:
VAR请求=要求(请求);
request.post('http://myvendorsapi.net/uploadPDF',功能(错误,对此,体){
如果(错误和放大器;!&安培; response.status code == 200){
VAR FORMDATA = {
容器名称:container1,
文件名:Texture_0.png,
文件:身体
};
request.post({URI:/ postAdvanced,FORMDATA:FORMDATA},功能optionalCallback(ERR,HTT presponse,体){
如果(ERR){
返回console.error('上传失败:,ERR);
}
的console.log(上传成功的服务器回应:!,正文);
});
} 其他 {
的console.log(获取快照失败!);
}
});
然后在后端code可能看起来像:
app.post('/ postAdvanced',功能(REQ,水库,下一个){
VAR容器名称= req.body.containerName;
VAR文件名= req.body.filename;
var文件= req.body.file;
如果(!Buffer.isBuffer(文件)){
//转换'文件'以二进制缓冲区
}
VAR的选择= {的contentType:图像/ PNG'};
blobSvc.createBlockBlobFromText(容器名称,文件名,文件,选项,功能(错误,结果,响应){
如果(!错误){
res.send(结果);
} 其他 {
执行console.log(错误);
}
});
})
If I post a PDF to my vendors API, they return me a .png file as a blob (see update 2 as I am now unsure if they are returning blob data).
I would like to push this into Azure Blob Storage. Using my code listed below, it pushes something in, but the file is corrupted. Example: downloading the .png from Azure Blob Storage and trying to open it with Paint gives the following error:
This is not a valid bitmap file, or its format is not currently supported.
I have verified that the image is sent to me correctly as the vendor is able to open the .png on their side. I am wondering if I need to convert this to base64 or save it to a local Web directory before uploading it to Azure Blob Storage.
Here is my Angular front end Controller that calls my Node/Express backend for uploading to Azure once it receives the returned "image":
$.ajax({
url: 'http://myvendorsapi.net/uploadPDF,
type: "POST",
data: formdata,
mimeType: "multipart/form-data",
processData: false,
contentType: false,
crossDomain: true,
success: function (result) {
var containerName = 'container1';
var filename = 'Texture_0.png';
var file = result;
$http.post('/postAdvanced', { containerName: containerName, filename: filename, file: file }).success(function (data) {
console.log("success!");
}, function (err) {
//console.log(err);
});
},
error: function (error) {
console.log("Something went wrong!");
}
})
}
Here is my Node/Express backend that uploads the blob to Azure Blob Storage. It gives no error, but the file can't be opened/gives the error stated above when opened in Paint:
app.post('/postAdvanced', function (req, res, next) {
var containerName = req.body.containerName;
var filename = req.body.filename;
var file = req.body.file;
blobSvc.createBlockBlobFromText(containerName, filename, file, function (error, result, response) {
if (!error) {
res.send(result);
}
else {
console.log(error);
}
});
})
Update 1: The answer provided here allows me to pass in the URL of the vendors API for some endpoints: Download file via Webservice and Push it to Azure Blob Storage via Node/Express
It works as it writes the file at the endpoint to a temp folder. In my current scenario, I upload a PDF file and it returns an image file that I need to upload to Azure Blob Storage. Is there a way to use the answer here, but adjust it for a file that I already have (since it is returned to me) versus file streaming from a URL?
Update 2: In console logging the returned "file", it looks like it may be data. I am not sure, it looks like this:
Is this actually data, and if so, how do I make this into a file for upload?
UPDATE 3:
Since it appears that jQuery AJAX can't manage binary returns. I am able to "open" the blob using XMLHTTPResponse as follows, but I can't seem to push this into Azure as it gives me the following error:
TypeError: must start with number, buffer, array or string
Here is my request. Note that the file opens properly:
var form = document.forms.namedItem("fileinfo");
form.addEventListener('submit', function (ev) {
var oData = new FormData(form);
var xhr = new XMLHttpRequest();
xhr.responseType = "arraybuffer";
xhr.open("POST", "http://myvendorsapi/Upload", true);
xhr.onload = function (oEvent) {
if (xhr.status == 200) {
var blob = new Blob([xhr.response], { type: "image/png" });
var objectUrl = URL.createObjectURL(blob);
window.open(objectUrl);
console.log(blob);
var containerName = boxContainerName;
var filename = 'Texture_0.png';
$http.post('/postAdvanced', { containerName: containerName, filename: filename, file: blob }).success(function (data) {
//console.log(data);
console.log("success!");
}, function (err) {
//console.log(err);
});
} else {
oOutput.innerHTML = "Error " + xhr.status + " occurred when trying to upload your file.<br \/>";
}
};
xhr.send(oData);
ev.preventDefault();
}, false);
createBlockBlobFromText will work with either string or buffer. You might need a buffer to hold the binary content due to a known issue of jQuery.
For a workaround, there are several options:
Option 1: Reading binary filesusing jquery ajax
Option 2: Use native XMLHttpRequest
Option 3: Write frontend with Node as well and browserify it. Your frontend code may look like:
var request = require('request');
request.post('http://myvendorsapi.net/uploadPDF', function (error, response, body) {
if (!error && response.statusCode == 200) {
var formData = {
containerName: 'container1',
filename: 'Texture_0.png',
file: body
};
request.post({ uri: '/postAdvanced', formData: formData }, function optionalCallback(err, httpResponse, body) {
if (err) {
return console.error('upload failed:', err);
}
console.log('Upload successful! Server responded with:', body);
});
} else {
console.log('Get snapshot failed!');
}
});
Then the backend code may look like:
app.post('/postAdvanced', function (req, res, next) {
var containerName = req.body.containerName;
var filename = req.body.filename;
var file = req.body.file;
if (!Buffer.isBuffer(file)) {
// Convert 'file' to a binary buffer
}
var options = { contentType: 'image/png' };
blobSvc.createBlockBlobFromText(containerName, filename, file, options, function (error, result, response) {
if (!error) {
res.send(result);
} else {
console.log(error);
}
});
})
这篇关于保存BLOB(可能是数据!)通过AJAX调用的Azure Blob存储返回创建损坏图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!