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

  • Post author:
  • Post category:java


一、开通对象存储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:8080/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中也看到相应的图片,测试成功



版权声明:本文为liulala16原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。