Unity上传文件到.net core 服务器并提供二维码下载
距离上一次分享,感觉过去了好久好久。最近手里的项目也完成的差不多了,接下来的几天(年前)会和大家分享一下在项目中收获的东西。
需求:用户使用App之后,可以保存当前屏幕截图,然后通过扫描二维码的形式下载图片到手机上。
环境:
- 前台:Unity
- 后台:asp.net core webapi
后台搭建
.net core 环境安装啥的我就不说了,去微软官网下载对应的SDK安装好。我使用的是.net core3.1,开发工具是VSCode。
创建工程
打开终端,输入 : dotnet new webapi
终端自动创建一个webpai的模板,我们对这个模板做一些修改(模板自带了一个天气查询的例子)。
找到 Controller/WeatherForecastController.cs,修改代码如下(具体请认真看代码注释代码注释):
using System.IO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Hosting;namespace FileUpload.Controllers
{/// /// 访问当前控制器使用的路由地址/// http://localhost/api/img/// [Route("api/img")]public class WeatherForecastController : Controller{private static readonly string[] Summaries = new[]{"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"};private readonly ILogger<WeatherForecastController> _logger;/// /// 使用.net core 的依赖注入,将要用到的实例注入进来/// private readonly IWebHostEnvironment _environment;public WeatherForecastController(ILogger<WeatherForecastController> logger,IWebHostEnvironment environment){_logger = logger;/// /// 使用.net core 的依赖注入,将要用到的实例注入进来/// _environment = environment ?? throw new ArgumentNullException(nameof(environment));}[HttpGet]public IEnumerable<WeatherForecast> Get(){var rng = new Random();return Enumerable.Range(1, 5).Select(index => new WeatherForecast{Date = DateTime.Now.AddDays(index),TemperatureC = rng.Next(-20, 55),Summary = Summaries[rng.Next(Summaries.Length)]}).ToArray();}/// /// 重要提示,函数的参数的名字必须保持和前端传来的字段名字相同/// 在发布窗体数据或直接使用 JavaScript FormData 的非 Razor 窗体中,/// 窗体元素或 FormData 指定的名称必须与控制器操作的参数名称相匹配。/// /// /// [HttpPost]public async Task<string> UploadImage(IFormFile file){/// /// 获取当前静态文件目录所在文件夹/// /// var uploads = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot");/// /// 按年月日时分秒的格式保存当前文件/// /// var fileName = DateTime.Now.ToString("yyyyMMddHHmmssffff") + ".jpg";var targetPath = Path.Combine(uploads, fileName);using (var steam = new FileStream(targetPath, FileMode.Create)){/// /// 将获取到的文件写入到服务器的指定目录中/// /// await file.CopyToAsync(steam);await steam.FlushAsync();steam.Close();/// /// 将当前接收到的文件的名字返回给前端/// return fileName;}}}
}
修改Startup.cs如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;namespace FileUpload
{public class Startup{public Startup(IConfiguration configuration){Configuration = configuration;}public IConfiguration Configuration { get; }// This method gets called by the runtime. Use this method to add services to the container.public void ConfigureServices(IServiceCollection services){services.AddControllers();//services.AddAuthentication(CertificateAuthenticationDefaults.)}// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.public void Configure(IApplicationBuilder app, IWebHostEnvironment env){if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}app.UseHttpsRedirection();///添加访问静态文件支持app.UseStaticFiles();app.UseRouting();app.UseAuthorization();app.UseEndpoints(endpoints =>{endpoints.MapControllers();});}}
}
修改Properties/launchSettings.json文件,在本机测试时不使用https协议,不然访问不到,等将代码上传到服务器之后才改回来即可。
{"$schema": "http://json.schemastore.org/launchsettings.json","iisSettings": {"windowsAuthentication": false,"anonymousAuthentication": true,"iisExpress": {"applicationUrl": "http://localhost:23643","sslPort": 44395}},"profiles": {"IIS Express": {"commandName": "IISExpress","launchBrowser": true,"launchUrl": "weatherforecast","environmentVariables": {"ASPNETCORE_ENVIRONMENT": "Development"}},"FileUpload": {"commandName": "Project","launchBrowser": true,"launchUrl": "weatherforecast","applicationUrl": "http://localhost:5000;","environmentVariables": {"ASPNETCORE_ENVIRONMENT": "Development"}}}
}
到这里后台代码搭建就完成了,如果你出了什么问题,请看代码注释。其它具体的细节请看微软官方文档。
前台搭建
前台当然是在我们熟悉的Unity中完成啦。
获取当前屏幕截图
public void StartScreenShoot(){StartCoroutine(ScreenSHOT());}
private IEnumerator ScreenShot(){yield return new WaitForEndOfFrame();//设置要截取的图片为矩形,大小和屏幕等高Texture2D screenShot = new Texture2D(Screen.height, Screen.height, TextureFormat.RGB24, false);var horizontalOffset = (Screen.width - Screen.height) / 2f;//读取屏幕中间部分的像素,高度和当前屏幕高度等高screenShot.ReadPixels(new Rect(horizontalOffset, 0, Screen.height, Screen.height), 0, 0);screenShot.Apply();yield return new WaitForEndOfFrame();}
将当前屏幕截图上传到服务器(请仔细看代码注释)
本例子中实现的是,将图片上传到服务器,服务器返回当前上传图片的文件名,用于网址访问
/// /// 将图片上传到自家服务器/// /// /// IEnumerator UploadTexture(Texture2D targetTexture){/// /// 将屏幕截图编码为字节流/// /// byte[] bytes = targetTexture.EncodeToJPG();/// /// 构建传输表单/// /// WWWForm wwwForm = new WWWForm();/// /// 重要:构建表单数据,这里的file字段必须保持和服务器对应函数的参数名称相同/// /// wwwForm.AddBinaryData("file", bytes, "myfile.jpg");/// /// 构建POST请求,打包时将下面网址替换为自己服务器的网址,也就是服务器对应的请求路由/// /// using (UnityWebRequest www = UnityWebRequest.Post("http://localhost:5000/api/img", wwwForm)){/// /// 声明一个内存缓冲,用于接收服务器传回的内容/// /// www.downloadHandler = new DownloadHandlerBuffer();/// /// 重要:指定当前传输的文件类型,如果不指定,服务器可能会识别不了/// /// www.uploadHandler.contentType = "multipart/form-data";yield return www.SendWebRequest();if (www.isHttpError || www.isNetworkError){Debug.Log("自己的服务器错误");loading.gameObject.SetActive(true);}else{//将接受到的图片在服务器的文件名和你自己的服务器域名组合起来var imagURL = "http://localhost:5000/" + www.downloadHandler.text;Debug.Log(imagURL);yield return StartCoroutine(GetCLQRCode(imagURL));}}}
将上一步中获取的图片网址编码为一个二维码,用户扫描二维码即可访问图片
生成二维码有很多种方式,这里使用最简单的一种。我们直接调用草料二维码提供的API接口来生成二维码。参考文章(https://www.jianshu.com/p/fece59a67860),看代码注释:
/// /// 从二维码提供商那里下载被转码后的二维码/// /// /// IEnumerator GetCLQRCode(string qrcodeImage){UnityWebRequest www = new UnityWebRequest();//构建GET请求,将需要编码的字符串包装到请求参数中string url = "https://cli.im/api/qrcode/code?text=" + qrcodeImage + "&mhid=t0uVWg+9ks4hMHcmLtBTOaM";www.url = url;Debug.Log(url);www.method = UnityWebRequest.kHttpVerbGET;www.downloadHandler = new DownloadHandlerBuffer();yield return www.SendWebRequest();if (www.isHttpError || www.isNetworkError){Debug.Log("二维码服务商错误");}else{/// /// 请求成功,草料API会返回一个html格式的网页,/// 需要对网页做一些内容截取,获取到返回的二维码的具体地址/// var w = www.downloadHandler.text;Debug.Log(w);string s = w.Substring(w.IndexOf("
) + 12, w.Length - (w.IndexOf("
) + 12));string result = s.Substring(0, s.IndexOf("\""));Debug.Log(result);UnityWebRequest qrcode = new UnityWebRequest();qrcode.url = result;qrcode.method = UnityWebRequest.kHttpVerbGET;qrcode.downloadHandler = new DownloadHandlerBuffer();yield return qrcode.SendWebRequest();if (qrcode.isHttpError || qrcode.isNetworkError){Debug.Log(qrcode.error);Debug.Log("访问二维码出错");}else{//构建一个texture2D用来存储二维码QRCodeTexture2D = new Texture2D(400, 400);yield return new WaitForSeconds(3f);//将接收到的图片数据写入构建的Texture2D中QRCodeTexture2D.LoadImage(qrcode.downloadHandler.data);QRCodeTexture2D.Apply();rawImage.gameObject.SetActive(true);//声明一个rawimage用来显示二维码rawImage.texture = QRCodeTexture2D;}Debug.Log("获取二维码成功");}}
完。
更多内容,欢迎关注:
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
