如何将Rest Controller生成的二维码展示到AngularJS页面?
解决AngularJS展示后端返回的二维码图片问题
看起来你遇到的核心问题是没有正确处理后端返回的图片字节数据,导致前端无法识别并渲染。下面我会一步步帮你排查问题,并给出可行的解决方案:
首先,明确后端返回的数据类型
你的Rest Controller返回的是"缓冲图片数据"(应该是byte[]或二进制流),而AngularJS的$http默认会把响应解析为JSON,这会导致二进制图片数据被损坏。所以第一步要修改请求配置,告诉AngularJS正确处理二进制数据。
方案1:使用Blob + ObjectURL(推荐,性能更好)
这种方式不需要把二进制数据转成base64,直接用浏览器的ObjectURL来渲染图片,内存占用更低。
步骤1:修改AngularJS控制器的请求代码
$http.post("../rest/a/save", {}, { responseType: 'blob' // 关键:告诉$http返回Blob类型的二进制数据 }).then(function(response){ // 创建Object URL,供img标签使用 $scope.qrcodeUrl = URL.createObjectURL(response.data); }); // 重要:控制器销毁时释放ObjectURL,避免内存泄漏 $scope.$on('$destroy', function() { if ($scope.qrcodeUrl) { URL.revokeObjectURL($scope.qrcodeUrl); } });
步骤2:HTML中直接使用img标签
<img ng-src="{{qrcodeUrl}}" alt="二维码" />
方案2:转换为Base64字符串渲染
如果你更习惯用base64的方式,可以把二进制数据转成base64字符串,再拼接成data URI。
步骤1:修改控制器代码
$http.post("../rest/a/save", {}, { responseType: 'arraybuffer' // 接收ArrayBuffer类型的二进制数据 }).then(function(response){ // 将ArrayBuffer转换为Uint8数组 var byteArray = new Uint8Array(response.data); // 转成base64字符串 var base64Str = btoa(String.fromCharCode.apply(null, byteArray)); // 拼接成图片的data URI $scope.qrcodeBase64 = 'data:image/png;base64,' + base64Str; });
步骤2:HTML中使用img标签
<img ng-src="{{qrcodeBase64}}" alt="二维码" />
修复你原来的自定义指令
如果你想继续使用av-qr指令,需要修改指令逻辑,让它能处理二进制数据或base64字符串,而不是把数据当成DOM元素:
app.directive('avQr', function() { return { restrict: 'E', template: '<img alt="二维码">', scope: { imageData: '<' // 接收Blob或base64字符串 }, link: function(scope, elem, attr) { var imgElement = elem.find('img'); // 监听imageData变化,更新图片 scope.$watch('imageData', function(newData) { if (!newData) return; // 先清理旧的资源 var oldSrc = imgElement.attr('src'); if (oldSrc && oldSrc.startsWith('blob:')) { URL.revokeObjectURL(oldSrc); } if (newData instanceof Blob) { // 处理Blob类型数据 imgElement.attr('src', URL.createObjectURL(newData)); } else if (typeof newData === 'string' && newData.startsWith('data:image/')) { // 处理base64的data URI imgElement.attr('src', newData); } }); // 指令销毁时清理资源 scope.$on('$destroy', function() { var src = imgElement.attr('src'); if (src && src.startsWith('blob:')) { URL.revokeObjectURL(src); } }); } } });
使用修改后的指令
如果用方案1的Blob数据:
$http.post("../rest/a/save", {}, {responseType: 'blob'}).then(function(response){ $scope.qrcodeData = response.data; });
<av-qr image-data="qrcodeData"></av-qr>
如果用方案2的base64数据:
<av-qr image-data="qrcodeBase64"></av-qr>
为什么你原来的方式不行?
- 你的自定义指令中
angular.element(scope.image)是错误的:scope.image是后端返回的二进制数据,不是DOM元素,直接append肯定无法渲染。 <div ng-bind-html="qrcode"></div>:qrcode是二进制数据,不是HTML字符串,而且即使转成HTML,也需要用$sce.trustAsHtml信任内容,否则AngularJS会过滤掉。<img data-ng-src='data:image/png;base64,{{qrcode}} />:qrcode是原始字节数据,不是base64字符串,所以拼接后无法被识别。
内容的提问来源于stack exchange,提问作者Manoj Kumar
相关产品推荐
相关产品推荐

