unity前端通过java后端实现将图片上传到阿里云OSS并在前端显示

news2024/10/6 1:41:24

一、开通对象存储OSS服务

     阿里云-搜索推荐

(1)申请阿里云账号

(2)实名认证

(3)开通对象存储oss服务

(4)进入管理控制台

(5)创建bucket

(6)在bucket的概览里查看bucket的名字与endpoint

(7)鼠标放在阿里云的头像上可以查看accessKey和secret,也可以为oss创建一个子用户accessKey

二、搭建java后台,创建一个springBoot项目或者模块

(1)修改pom.xml,引入阿里云oss依赖

    <dependencies>
        <!-- 阿里云oss依赖 -->
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
        </dependency>
      <!--web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

(2)添加配置文件application.yml

server:
  port: 8080

spring:
  application:
    name: service-oss

aliyun:
  oss:
    access-key: 第一步记录的access-key
    endpoint: oss-cn-beijing.aliyuncs.com
    bucket:  创建的bucket的名称
    secret-key: 第一步记录的secret-key

(3)创建返回结果的枚举类ResultCodeEnum


import lombok.Getter;

/**
 * 统一返回结果状态信息类
 * @author superman
 */
@Getter
public enum ResultCodeEnum {

    SUCCESS(200,"成功"),
    FAIL(201, "失败"),
    PARAM_ERROR( 202, "参数不正确"),
    SERVICE_ERROR(203, "服务异常"),
    DATA_ERROR(204, "数据异常"),
    DATA_UPDATE_ERROR(205, "数据版本异常"),

    LOGIN_AUTH(208, "未登陆"),
    PERMISSION(209, "没有权限"),

    CODE_ERROR(210, "验证码错误"),

    CODE_SENDFAST(211, "短信发送频率过快"),
    LOGIN_DISABLED_ERROR(212, "该用户已被禁用"),
    REGISTER_MOBLE_ERROR(213, "手机号已被使用"),
    LOGIN_AURH(214, "需要登录"),
    LOGIN_ACL(215, "没有权限"),

    URL_ENCODE_ERROR( 216, "URL编码失败"),
    ILLEGAL_CALLBACK_REQUEST_ERROR( 217, "非法回调请求"),
    FETCH_ACCESSTOKEN_FAILD( 218, "获取accessToken失败"),
    FETCH_USERINFO_ERROR( 219, "获取用户信息失败"),

   
    private Integer code;
    private String message;

    ResultCodeEnum(Integer code, String message) {
        this.code = code;
        this.message = message;
    }
}

(4)创建统一返回结果类Result


import lombok.Data;

/**
 * 全局统一返回结果类
 */
@Data
public class Result<T> {

    private Integer code;

    private String message;

    private T data;

    public Result(){}

    protected static <T> Result<T> build(T data) {
        Result<T> result = new Result<T>();
        if (data != null) {
            result.setData(data);
        }
        return result;
    }

    public static <T> Result<T> build(T body, ResultCodeEnum resultCodeEnum) {
        Result<T> result = build(body);
        result.setCode(resultCodeEnum.getCode());
        result.setMessage(resultCodeEnum.getMessage());
        return result;
    }

    public static <T> Result<T> build(Integer code, String message) {
        Result<T> result = build(null);
        result.setCode(code);
        result.setMessage(message);
        return result;
    }

    public static<T> Result<T> ok(){
        return Result.ok(null);
    }

    /**
     * 操作成功
     * @param data
     * @param <T>
     * @return
     */
    public static<T> Result<T> ok(T data){
        Result<T> result = build(data);
        return build(data, ResultCodeEnum.SUCCESS);
    }

    public static<T> Result<T> fail(){
        return Result.fail(null);
    }

    /**
     * 操作失败
     * @param data
     * @param <T>
     * @return
     */
    public static<T> Result<T> fail(T data){
        Result<T> result = build(data);
        return build(data, ResultCodeEnum.FAIL);
    }

    public Result<T> message(String msg){
        this.setMessage(msg);
        return this;
    }

    public Result<T> code(Integer code){
        this.setCode(code);
        return this;
    }

    public boolean isOk() {
        if(this.getCode().intValue() == ResultCodeEnum.SUCCESS.getCode().intValue()) {
            return true;
        }
        return false;
    }
}

(5)创建启动类

import org.springframework.boot.SpringApplication;
import org.springframework.context.annotation.ComponentScan;

/**
 * @author superman
 */
@SpringBootApplication()
@ComponentScan(basePackages = "com.liulala")
public class ServiceOssApplication {
    public static void main(String[] args) {
        SpringApplication.run(ServiceOssApplication.class, args);
    }
}

(6)创建一个从配置文件中获取阿里云oss各种配置参数的配置类

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * @author superman
 */
@Component
public class ConstantOssPropertiesUtils implements InitializingBean {

    @Value("${aliyun.oss.access-key}")
    private String accessKey;
    @Value("${aliyun.oss.endpoint}")
    private String endpoint;
    @Value("${aliyun.oss.bucket}")
    private String bucket;
    @Value("${aliyun.oss.secret-key}")
    private String secretKey;

    public static String ENDPOINT;
    public static String ACCESS_KEY_ID;
    public static String SECRET_KEY;
    public static String BUCKET;

    @Override
    public void afterPropertiesSet() {
        ENDPOINT = endpoint;
        ACCESS_KEY_ID = accessKey;
        SECRET_KEY = secretKey;
        BUCKET = bucket;
    }
}

(7)创建controller类

import com.liulala.common.result.Result;
import com.liulala.oss.service.FileService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

/**
 * @author superman
 */
@RestController
@RequestMapping("/api/oss/file")
public class FileApiController {

    @Autowired
    FileService fileService;

    @PostMapping("fileUpload")
    public Result fileUpload(MultipartFile file){
        String url = fileService.upload(file);
        return Result.ok(url);
    }
}

(8)创建service接口

import org.springframework.web.multipart.MultipartFile;

/**
 * @author superman
 */
public interface FileService {
    /**
     * 上传
     * @param file
     * @return
     */
    String upload(MultipartFile file);
}

(8)创建service接口的实现类FileServiceImpl

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.liulala.oss.service.FileService;
import com.liulala.oss.utils.ConstantOssPropertiesUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

/**
 * @author superman
 */
@Service
public class FileServiceImpl implements FileService {
    @Override
    public String upload(MultipartFile file) {

        String endpoint = ConstantOssPropertiesUtils.ENDPOINT;
        String accessKeyId = ConstantOssPropertiesUtils.ACCESS_KEY_ID;
        String accessKeySecret = ConstantOssPropertiesUtils.SECRET_KEY;
        String bucketName = ConstantOssPropertiesUtils.BUCKET;

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            InputStream inputStream = file.getInputStream();
            String format = new SimpleDateFormat("yyyy/MM/dd").format((new Date()));
            String uuid = UUID.randomUUID().toString().replaceAll("-","");
            String filename = format + "/" + uuid+ file.getOriginalFilename();
            // 创建PutObject请求。
            ossClient.putObject(bucketName, filename, inputStream);
            String url = "https://"+bucketName+"."+endpoint+"/"+filename;
            return url;
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return null;
    }
}

三、搭建unity前端

(1)创建一个接受后端结果的Result类

public class Result<T> 
{
    public int code;
    public string message;
    public T data;

    public Result()
    {
    }
}

(2)编写主逻辑脚本UpLoadImageCtrl

using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;

public class UpLoadImageCtrl : MonoBehaviour
{
    public RawImage headTexture;//在本地显示的图片
    public Texture2D tx;//要上传到oss的图片
    void Start()
    {
        
    }
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Alpha0))
        {
            StartCoroutine(UploadImageToOSS());
        }
    }
  
    //上传图片到OSS
    IEnumerator UploadImageToOSS()
    {
        WWWForm form = new WWWForm();
        form.AddBinaryData("file", tx.EncodeToPNG());
        UnityWebRequest webRequest = UnityWebRequest.Post("http://localhost:8205/api/oss/file/fileUpload", form);

        yield return webRequest.SendWebRequest();
        if (webRequest.result == UnityWebRequest.Result.ProtocolError ||
            webRequest.result == UnityWebRequest.Result.ConnectionError) //如果其 请求失败,或是 网络错误
        {
            Debug.Log(webRequest.error);
        }
        else
        {
            string result = webRequest.downloadHandler.text;
            var resultEntity = JsonUtility.FromJson<Result<string>>(result);
            print("code:"+resultEntity.code);
            print("message:" + resultEntity.message);
            print("data:" + resultEntity.data);
            if (resultEntity.code == 200) {
                //获取后台传过来的图片url
                string imageUrl = resultEntity.data;
                StartCoroutine(GetImageFromOSS(imageUrl));
            }          
        }
    }

    //从OSS中获取图片
    IEnumerator GetImageFromOSS(string imgUrl)
    {
        UnityWebRequest unityWebRequest = UnityWebRequest.Get(imgUrl); //创建UnityWebRequest对象
        yield return unityWebRequest.SendWebRequest(); //等待返回请求的信息
        if (unityWebRequest.result == UnityWebRequest.Result.ProtocolError ||
            unityWebRequest.result == UnityWebRequest.Result.ConnectionError) //如果其 请求失败,或是 网络错误
        {
            Debug.Log(unityWebRequest.error); //打印错误原因
        }
        else //请求成功
        {      
            //通过data拿到图片二进制流
            byte[] data = unityWebRequest.downloadHandler.data;
            int width = 900;
            int height = 1200;
            Texture2D texture = new Texture2D(width, height);
            texture.LoadImage(data);
            headTexture.texture = texture;
        }
    }
}

(3)搭建scene,创建一个RawImage,用于显示上传图片,将UpLoadImageCtrl 脚本挂在主相机上,Tx为本地一张测试图片,用于上传到oss服务器

 注意:测试图片格式为default

 四、测试

在编辑器模式下运行unity,按键盘0测试,可以看到unity端已经回显出从oss获得的图片,也打印出结果,在阿里云的oss中也看到相应的图片,测试成功

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/115715.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于注解的自动装配之@Autowired的原理及注意事项

基于注解的自动装配之Autowired的原理及注意事项 1. Autowired的原理 首先根据所需要的组件类型到IOC容器中查找 能够找到唯一的bean&#xff1a;直接执行装配 如果完全找不到匹配这个类型的bean&#xff1a;装配失败 和所需类型匹配的bean不止一个 没有Qualifier注解&#…

YGG 与 Mike Ovecka 对 Web3 电子竞技的愿景

&#xff08;从左到右&#xff09;YGG 内容创作者 Een Mercado、Ampverse Web3 负责人 Sascha Jochum、Axie Infinity 菲律宾负责人 Nix Eniego、MetaSports 联合创始人兼 CEO Joe Josue 和 YGG 电子竞技负责人 Mike Ovecka 在 Philippine Web3 Festival 的“区块链游戏电子竞…

MybatisPlus代码生成器配置(处理blob等类型)

一&#xff1a;新建springboot项目 二&#xff1a;导包 <dependencies><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.3.2</version></dependency><depe…

ATJ2158界面绘制LVGL---定时器

LVGL定时器 在lv_timer.c中有相关的操作函数 Create a timer&#xff08;创建定时器&#xff09; LVGL 有一个内置的定时器系统。可以注册一个函数以定期调用它。定时器在lv_timer_handler()中被处理和调用&#xff0c;它需要每隔几毫秒调用一次 Ready and Reset&#xff0…

fio磁盘压测工具

文章目录背景安装测试如何模拟现实中的IOfio参数解释【1】随机读测试【2】随机写测试【3】 顺序读测试【4】 顺序写测试numjobs5 测试随机读随机写顺序读顺序写blktracefio 模拟真实IO场景查看 blktrace 记录的结果将结果转化为二进制文件使用 fio 重放日志结论背景 因为是虚拟…

Oracle 备份与恢复常见的七大问题

为了最大限度保障数据的安全性&#xff0c;同时能在不可预计灾难的情况下保证数据的快速恢复&#xff0c;需要根据数据的类型和重要程度制定相应的备份和恢复方案。在这个过程中&#xff0c;DBA的职责就是要保证数据库&#xff08;其它数据由其它岗位负责&#xff09;的高可用和…

Linux常用操作(下)

目录 文件传输 全局查找 管道符 统计数目 vim快捷键 软件安装 用户和组 文件权限 文件传输 yum install lrzsz -y rpm -qa |grep lrzsz 完成后直接将文件拖入xshell即可 全局查找 grep 字符串 文件名 grep colea * grep -r colea *//递归全局查找 管道符 ps -ef…

边缘AI概述

随着移动计算和物联网&#xff08;IoT&#xff09;应用程序的爆炸性增长&#xff0c;数十亿移动和物联网设备正在连接到互联网&#xff0c;在网络边缘生成大量数据。因此&#xff0c;在云数据中心收集大量数据会产生极高的延迟和网络带宽使用。 因此&#xff0c;迫切需要将人工…

K8S——调用亲和性

k8s-调度亲和性 简介 Scheduler 是 kubernetes 的调度器&#xff0c;主要的任务是把定义的 pod 分配到集群的节点上。听起来非常简单&#xff0c;但有 很多要考虑的问题&#xff1a; 公平&#xff1a;如何保证每个节点都能被分配资源资源高效利用&#xff1a;集群所有资源最…

为什么NoSQL数据库这么受欢迎?

大数据时代&#xff0c;NoSQL数据库是企业构建数据能力的核心工具之一。近期&#xff0c;在2022腾讯全球数字生态大会NoSQL数据库专场上&#xff0c;腾讯云发布了多项NoSQL产品能力升级&#xff0c;并重点讲解了其背后的自研技术要点及实现细节&#xff0c;分享了腾讯云NoSQL为…

利用Python自动生成请假条,实现高效摸鱼

哈喽兄弟们&#xff0c;今天咱们来实现用Python来批量生成请假条&#xff0c;这回既学了东西又做了事情&#xff0c;两不误~ 本文就将基于一个真实的办公案例进行讲解如何提取Excel内容并创建Word 主要将涉及以下三个知识点 openpyxl 读取 Excel 文件python-docx 写入 Word …

org.springframework.jdbc.BadSqlGrammarException: Error updating database

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; org.springframework.jdbc.BadSqlGrammarException: Error updating database 报错信息&#xff1a; org.springframework.jdbc.BadSqlGrammarException: Error updat…

Python基础入门(一)

文章目录前言Python起源简介常量和表达式什么是变量变量的语法变量的定义变量的命名规则使用变量变量的类型动态类型的变量注释注释是什么注释的基本语法注释的书写规范输入输出通过控制台输出格式化输出输入转义字符运算符算数运算符关系运算符逻辑运算符赋值运算符复合赋值运…

Python高频面试题——迭代器和可迭代对象

无论是面试测试还是运维涉及到python编码岗位时&#xff0c;迭代器和可迭代对象都是绕不开的一个问题&#xff0c;本文对这两个概念进行重点讲解&#xff0c;本文从什么是迭代讲起&#xff0c;然后介绍迭代器和可迭代对象二者的区别&#xff0c;最后通过for 循环和自定义迭代器…

150万奖金:首届6G智能无线通信系统大赛正式上线

通信与人工智能技术的深度融合已成为无线通信系统发展的最重要方向之一&#xff0c;面向6G&#xff0c;通信与AI融合的角度和深度将进一步扩展&#xff0c;迎接“无限”可能。在6G研究的关键发展阶段&#xff0c;由IMT-2030(6G)推进组主办&#xff0c;中国信息通信研究院、华为…

【折腾服务器 3】群晖学习版中安装 Active Backup for Business 及相关配置 =)

Catch UP 书接上回&#xff0c;在 ESXi 中安装了群晖系统&#xff0c;这个系统主要是用来给 Windows 物理机做备份的&#xff0c;因此在本片主要讲解如何配置 Active Backup for Business 软件。 Chapter 1 设置存储空间 上一篇博客中&#xff0c;安装群晖时分配了一个 32GB…

rancher2.6.2 单机及高可用部署

rancher2.6.2 单机及高可用部署 文章目录rancher2.6.2 单机及高可用部署前言单机部署高可用部署k8s集成前言 1、服务器准备 单机部署&#xff1a; 机器名IP地址部署内容cpu核心数内存(G)硬盘(G)rancher-master192.168.0.18rancher2450 高可用部署&#xff1a; 机器名IP地址…

Linux环境下通过命令行连接WIFI

一. 前言 在调试ARTIK时由于Ubuntu系统不是图形化界面&#xff0c;需要下载相关安装包时发现未联网&#xff0c;因此对Linux下采用命令行连接wifi的具体操作步骤进行总结&#xff0c;对自己在操作过程中遇到的相关问题解决方法进行介绍&#xff0c;同时对于LINUX下无线网络调试…

JUC(一):线程池

个人博客地址&#xff1a; http://xiaohe-blog.top/index.php/archives/14/ 文章目录1. 为什么要使用线程池2. Executor3. ThreadPoolExecutor3.1 七个参数3.2 任务队列3.3 拒绝策略4. 创建线程池5. Executors5.1 CachedThreadPool5.2 FixedThreadPool5.3 SingleThreadExecutor…

Vue3 异步组件 suspense

vue在解析我们的组件时&#xff0c; 是通过打包成一个 js 文件&#xff0c;当我们的一个组件 引入过多子组件是&#xff0c;页面的首屏加载时间 由最后一个组件决定 优化的一种方式就是采用异步组件 &#xff0c;先给慢的组件一个提示语或者 骨架屏 &#xff0c;内容回来在显示…