Vue.js结合Django REST显示MSSQL二进制图片问题求助
Vue+Django+MSSQL 二进制图片无法显示问题排查与解决
问题背景
我通过用户表单将图片以二进制形式存储到MSSQL数据库,现在需要在用户个人页面展示该图片。技术栈为Vue.js、Django和MSSQL,后端功能正常,但前端图片显示异常。
初始问题:使用GET请求获取图片时,页面仅显示图片占位图标,提示URL无效。
更新后状态
URL无效提示已消失,但图片仍无法显示,且无任何报错信息。我已做以下代码更新:
- Vue组件中添加:
imgElement.src= "data:image/jpeg;base64," + btoa(studentPicUrl); - apiservice.js中添加:
const imageBlob = new Blob([response_pic.data], { type: 'image/jpeg' });
MSSQL中图片字段数据类型为image,相关代码如下:
代码片段
views.py
class studentPictures(APIView): def get(self, request, cnic, *args, **kwargs): try: stdpics = StudentPictures.objects.filter(std_cnic=cnic).first() # Serialize the StudentPictures instance serializer = StudentPicturesSerializer(stdpics) return Response(serializer.data, status=status.HTTP_200_OK) except StudentPictures.DoesNotExist: return Response({"error": "Student Pictures not found"}, status=status.HTTP_404_NOT_FOUND) except Exception as e: return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) def put(self, request, cnic, *args, **kwargs): print("put called", cnic) stdpics_data = StudentPictures.objects.filter(std_cnic=cnic).first() if stdpics_data is not None: image = request.FILES['image'] file_content = image.read() stdpics_data.image= file_content serializer = StudentPicturesSerializer(instance=stdpics_data,data= request.data,partial=True) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_200_OK) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) return Response({"res": "Object does not exist"}, status=status.HTTP_400_BAD_REQUEST)
models.py
class StudentPictures(models.Model): std_pic_id = models.AutoField(primary_key=True) std_cnic = models.ForeignKey(Student, models.DO_NOTHING, db_column='std_cnic') image = models.BinaryField(blank=True, null=True) class Meta: managed = False db_table = 'student_pictures'
apiservice.js
try { const response_pic = await axios.get(`${BASE_URL}/studentpic/${cnic}`, { responseType: 'blob', // Specify responseType as 'blob' }); // Check if the response contains image data if (response_pic.data) { // Convert the binary data to a Blob object const imageBlob = new Blob([response_pic.data]); // Create a URL for the Blob const imageUrl = URL.createObjectURL(imageBlob); // Store the URL in session storage sessionStorage.setItem('student_pic_url', imageUrl); alert(imageUrl) } } catch (error) { console.error('Error fetching student picture data:', error); throw error; // Rethrow the error to handle it in the calling function }
Vue组件mounted钩子
mounted() { // Check if the session storage exists const studentPicUrl = sessionStorage.getItem('student_pic_url'); console.log(studentPicUrl); // Set the src attribute of the img element const imgElement = document.getElementById('studentImage'); if (studentPicUrl) { // If session storage exists, set the src to the session storage imgElement.src = studentPicUrl; console.log("image is present"); } else { // If session storage does not exist, set the src to the default image URL const defaultImageUrl = require('@/assets/img/default.jpeg'); // Adjust the path accordingly imgElement.src = defaultImageUrl; console.log("no image"); } }
解决思路
1. 后端返回方式优化(推荐)
当前Django后端返回的是序列化后的JSON数据,二进制图片直接序列化会导致编码丢失,前端无法解析成正确的图片流。修改后端GET接口,直接返回二进制图片响应:
def get(self, request, cnic, *args, **kwargs): try: stdpics = StudentPictures.objects.filter(std_cnic=cnic).first() if not stdpics or not stdpics.image: return Response({"error": "Student Pictures not found"}, status=status.HTTP_404_NOT_FOUND) # 直接返回二进制图片,指定Content-Type return HttpResponse(stdpics.image, content_type='image/jpeg') except Exception as e: return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
此时前端无需额外处理二进制转Blob,直接用responseType: 'blob'获取后创建ObjectURL即可。
2. 序列化器转Base64处理
如果必须通过JSON返回图片数据,在序列化器中将二进制图片转成Base64字符串:
from base64 import b64encode class StudentPicturesSerializer(serializers.ModelSerializer): image = serializers.SerializerMethodField() def get_image(self, obj): if obj.image: return b64encode(obj.image).decode('utf-8') return None class Meta: model = StudentPictures fields = ['image']
前端拿到Base64字符串后,拼接成data URL使用:
// apiservice.js中改为responseType: 'json' const response_pic = await axios.get(`${BASE_URL}/studentpic/${cnic}`); if (response_pic.data.image) { const imageUrl = `data:image/jpeg;base64,${response_pic.data.image}`; sessionStorage.setItem('student_pic_url', imageUrl); }
3. 前端错误逻辑修正
之前尝试的btoa(studentPicUrl)属于错误操作——studentPicUrl已经是Blob URL,无需转Base64,该操作会破坏URL结构导致图片无法加载,需移除该代码。
内容的提问来源于stack exchange,提问作者laiba masood
相关产品推荐
相关产品推荐

