这边文章主要叙述如何将图片文件上传到服务器,服务器如何接收保存,关于如何用网页展示图片,并结合微信分享将另开文章叙述。


文件上传

之前文件上传一直使用的是FTP,后来由于使用了阿里云,云服务器对于FTP的请求方式有一定的限制,从客户端角度来说,需要设置为主动模式,导致原来的代码即使这么设置,仍然无法访问,因此后来改成了HTTP的传输方式(即unity的www请求一个url,服务器用php准备好这个url),所以目前是将图片文件转为base64的字符串,通过Post传给服务器。

base64转换

//图片转base64string
    public string Texture2dToBase64(string texture2d_path)
    {
        //将图片文件转为流文件
        FileStream fs = new System.IO.FileStream(texture2d_path, System.IO.FileMode.Open, System.IO.FileAccess.Read);
        byte[] thebytes = new byte[fs.Length];
        fs.Read(thebytes, 0, (int)fs.Length);
        //转为base64string
        string base64_texture2d = Convert.ToBase64String(thebytes);
        return base64_texture2d;
    }

Post请求

Unity2018及再之后,WWW的方法需要改写,以下代码可能过时。这里在接口定义层面,需要服务器的php在处理完成之后返回处理状态:0000 上传成功 其他的表示一种错误情况。filename表示文件名,不含路径,urlpath表示你要传的相对位置。由于拍照活动有很多,文件上传是可以复用的,所以会有urlpath这样的字段。

IEnumerator UploadFile()
    {

        print("开始上传文件:" + filename);
        WWWForm form = new WWWForm();
        form.AddField("filename", filename);
        form.AddField("urlpath", urlpath);

        form.AddField("data", Texture2dToBase64(filepath));
        WWW www = new WWW("www.你的域名.com/upload.php", form);
        //UnityWebRequest request = UnityWebRequest.Post ("www.你的域名.com/upload.php", form);
        yield return www;
        //yield return request;

        if( www.text.Trim() == "0000")
        {
            result = 1;
            print("上传成功");
        }
        else
        {
            print(www.text);
            result = 0;
            //print("上传失败");
        }
        //if (request.ToString().Trim() == "0000")
        //{
        //    result = 1;
        //    print("上传成功");
        //}
        //else
        //{
        //    print(request.ToString());
        //    result = 0;
        //    //print("上传失败");
        //}

    }

服务器接收

服务器是基于宝塔面板建立的,我使用了php5.6去写接收文件的代码,由于拍照应用运行环境比较单纯,所以我没有实现除了0000返回码以外的返回码逻辑。代码比较简单,就是锁定好要上传的路径,得到data,解base64码,写入文件。

<?php
    $filename = $_POST['filename'];
    $urlpath = $_POST['urlpath'];

    if(!(substr($urlpath,strlen($urlpath)-1,strlen($urlpath)) == '/'))
        $urlpath  = $urlpath.'/';
    $base_img = $_POST['data'];
    $ifp = fopen( '../'.$urlpath.$filename, "wb" );
    fwrite( $ifp, base64_decode( $base_img) );
    fclose( $ifp );
    //file_put_contents('index.txt',$filename); //如果文件不存在创建文件,并写入内容
    echo "0000";
?>

客户端生成二维码

用ZXing,ZXing是一个支持在图像中解码和生成条形码(如二维码)的库。是一个开源的实现的一维/二维条码图像处理库,有到对unity的专门的支持,下载资源:ZXing-Unity部分-可生成二维码的库

这里说明一下URL需要根据你展示图片的网页文件去决定,比如我的是showpic.php,GET方式获取参数,那么下文代码中的str应该是 http://www.xxx.com/showpic.php?filename=1001.jpg

using System.Collections;
using UnityEngine;
using System.IO;
using System;
using ZXing;
using ZXing.QrCode;
using UnityEngine.UI;

public class FileUpload : MonoBehaviour {
    
    /// <summary>
    /// 返回指定URL的二维码
    /// </summary>
    /// <param name="str">url,比如http://www.xxx.com/showpic.php?filename=1001.jpg</param>
    /// <returns></returns>
    public Texture2D ShowCode(string str)
    {
        encoded = new Texture2D(256, 256);
        //QRCodes = str;
        var textForEncoding = str ;
        if (textForEncoding != null)
        {
            //二维码写入图片
            var color32 = Encode1(textForEncoding, encoded.width, encoded.height);
            encoded.SetPixels32(color32);
            encoded.Apply();
            return encoded;
        }
        return null;
    }

    //定义方法生成二维码
    private static Color32[] Encode1(string textForEncoding, int width, int height)
    {
        var writer = new BarcodeWriter
        {
            Format = BarcodeFormat.QR_CODE,
            Options = new QrCodeEncodingOptions
            {
                Height = height,
                Width = width
            }
        };
        return writer.Write(textForEncoding);
    }
}