通过在线源统一在手机上保存图像

时间:2017-04-15 01:22:14

标签: c# unity3d web scripting filesystems

主要目标:从在线网址加载图片,然后在移动设备上的/ Repo / {VenueName}目录中将图片(任何类型)保存在本地。这样就可以节省未来的移动数据,当场景加载首先检查本地图像然后调用www请求,如果它已经不存在于移动设备上。

我已经在线获取图片,我已经从json文件中提取了网址,现在我想将它们本地存储在移动设备上,以便为最终用户保存数据传输。

我已经使用持久数据路径和IO.director进行了循环,并不断遇到问题。

目前我已经有了一个从网上保存文本并成功将其存储在设备上的功能,但如果我将它用于图像,由于下面显示的字符串参数,它不会工作,我尝试过将它转换为字节编辑功能,而不是传递它www.text并得到图像损坏错误。

这是我用于保存文本文件的旧功能。

public void writeStringToFile( string str, string filename ){
        #if !WEB_BUILD
            string path = pathForDocumentsFile( filename );
            FileStream file = new FileStream (path, FileMode.Create, FileAccess.Write);

            StreamWriter sw = new StreamWriter( file );
            sw.WriteLine( str );

            sw.Close();
            file.Close();
        #endif  
    }


public string pathForDocumentsFile( string filename ){ 
        if (Application.platform == RuntimePlatform.IPhonePlayer)
        {
            string path = Application.dataPath.Substring( 0, Application.dataPath.Length - 5 );
            path = path.Substring( 0, path.LastIndexOf( '/' ) );
            return Path.Combine( Path.Combine( path, "Documents" ), filename );
        }else if(Application.platform == RuntimePlatform.Android){
        string path = Application.persistentDataPath;   
            path = path.Substring(0, path.LastIndexOf( '/' ) ); 
            return Path.Combine (path, filename);
        }else {
            string path = Application.dataPath; 
            path = path.Substring(0, path.LastIndexOf( '/' ) );
            return Path.Combine (path, filename);
        }
    }

这适用于文本,因为它需要一个字符串,但无论我编辑多少,我都无法处理它。

我最终走了一条不同的路线,但是使用以下代码进行了未经授权的访问问题,并且认为它不适用于移动设备,但是......

IEnumerator loadPic(WWW www, string thefile, string folder)
 {
    yield return www;
     string venue = Application.persistentDataPath + folder;
     string path = Application.persistentDataPath + folder + "/" + thefile;

    if (!System.IO.Directory.Exists(venue))
     {
        System.IO.Directory.CreateDirectory(venue);
     }

    if (!System.IO.Directory.Exists(path))
     {
        System.IO.Directory.CreateDirectory(path);
     }

    System.IO.File.WriteAllBytes(path, www.bytes);
 }

呃,这是凌晨3点,我无法弄清楚,你们可以帮助我吗?提前谢谢。

2 个答案:

答案 0 :(得分:5)

  

我试图将它转换为字节编辑功能而不是   通过它www.text并得到图像损坏错误

这可能是你问题 90%的原因。 WWW.text用于非二进制数据,例如简单文本。

1 。下载WWW.bytes而不是WWW.text的图片或文件。

2 。使用File.WriteAllBytes保存图片。

3 。使用File.ReadAllBytes阅读图片。

4 。使用Texture2D.LoadImage(yourImageByteArray);

将图像加载到纹理

5 。如果您希望此路径与每个平台兼容,则您的路径必须为Application.persistentDataPath/yourfolderName/thenFileName不应该<{1}}或Application.persistentDataPath/yourFileName

6 。最后,使用Application.dataPath查看代码中发生了什么。您必须或至少使用调试器。您需要准确了解代码失败的位置。

您仍然需要执行一些错误检查。

Debug.Log

<强>用法

准备网址以从中下载图片并保存到:

public void downloadImage(string url, string pathToSaveImage)
{
    WWW www = new WWW(url);
    StartCoroutine(_downloadImage(www, pathToSaveImage));
}

private IEnumerator _downloadImage(WWW www, string savePath)
{
    yield return www;

    //Check if we failed to send
    if (string.IsNullOrEmpty(www.error))
    {
        UnityEngine.Debug.Log("Success");

        //Save Image
        saveImage(savePath, www.bytes);
    }
    else
    {
        UnityEngine.Debug.Log("Error: " + www.error);
    }
}

void saveImage(string path, byte[] imageBytes)
{
    //Create Directory if it does not exist
    if (!Directory.Exists(Path.GetDirectoryName(path)))
    {
        Directory.CreateDirectory(Path.GetDirectoryName(path));
    }

    try
    {
        File.WriteAllBytes(path, imageBytes);
        Debug.Log("Saved Data to: " + path.Replace("/", "\\"));
    }
    catch (Exception e)
    {
        Debug.LogWarning("Failed To Save Data to: " + path.Replace("/", "\\"));
        Debug.LogWarning("Error: " + e.Message);
    }
}

byte[] loadImage(string path)
{
    byte[] dataByte = null;

    //Exit if Directory or File does not exist
    if (!Directory.Exists(Path.GetDirectoryName(path)))
    {
        Debug.LogWarning("Directory does not exist");
        return null;
    }

    if (!File.Exists(path))
    {
        Debug.Log("File does not exist");
        return null;
    }

    try
    {
        dataByte = File.ReadAllBytes(path);
        Debug.Log("Loaded Data from: " + path.Replace("/", "\\"));
    }
    catch (Exception e)
    {
        Debug.LogWarning("Failed To Load Data from: " + path.Replace("/", "\\"));
        Debug.LogWarning("Error: " + e.Message);
    }

    return dataByte;
}

如您所见,无需将图像扩展名( png jpg )添加到 savePath ,而您不应该在保存路径中添加图片扩展名。如果您不知道扩展程序,这将使以后加载更容易。只要图像是 png jpg 图像格式,它就应该有效。

下载文件:

//File url
string url = "http://www.wallpapereast.com/static/images/Cool-Wallpaper-11C4.jpg";
//Save Path
string savePath = Path.Combine(Application.persistentDataPath, "data");
savePath = Path.Combine(savePath, "Images");
savePath = Path.Combine(savePath, "logo");

从文件加载图片:

downloadImage(url, savePath);

将图像放到Texture2D:

byte[] imageBytes = loadImage(savePath);

答案 1 :(得分:1)

@Programmer的答案是正确的,但是我已经更新了它已经过时了:

万维网已过时

  

UnityWebRequest替代了Unity的原始WWW对象。它提供了用于组合HTTP请求和处理HTTP响应的模块化系统。 UnityWebRequest系统的主要目标是允许Unity游戏与现代Web后端进行交互。它还支持高要求功能,例如分块的HTTP请求,流式POST / PUT操作以及对HTTP标头和动词的完全控制。   https://docs.huihoo.com/unity/5.4/Documentation/en/Manual/UnityWebRequest.html

UnityWebRequest.GetTexture已过时

  

注意:UnityWebRequest.GetTexture已过时。请改用UnityWebRequestTexture.GetTexture。

     

注意:仅支持JPG和PNG格式。

     

UnityWebRequest已正确配置为下载图像并将其转换为Texture。

     

https://docs.unity3d.com/ScriptReference/Networking.UnityWebRequestTexture.GetTexture.html

using System;
using System.Collections;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;

public class ImageDownloader : MonoBehaviour
{

    private void Start()
    {
        //File url
        string url = "https://www.stickpng.com/assets/images/58482b92cef1014c0b5e4a2d.png";
        //Save Path
        string savePath = Path.Combine(Application.persistentDataPath, "data");
        savePath = Path.Combine(savePath, "Images");
        savePath = Path.Combine(savePath, "logo.png");
        downloadImage(url,savePath);
    }
    public void downloadImage(string url, string pathToSaveImage)
    {
        StartCoroutine(_downloadImage(url,pathToSaveImage));
    }

    private IEnumerator _downloadImage(string url, string savePath)
    {
        using (UnityWebRequest uwr = UnityWebRequestTexture.GetTexture(url))
        {
            yield return uwr.SendWebRequest();

            if (uwr.isNetworkError || uwr.isHttpError)
            {
                Debug.LogError(uwr.error);
            }
            else
            {
                Debug.Log("Success");
                Texture myTexture = DownloadHandlerTexture.GetContent(uwr);
                byte[] results = uwr.downloadHandler.data;
                saveImage(savePath, results);

            }
        }
    }

    void saveImage(string path, byte[] imageBytes)
    {
        //Create Directory if it does not exist
        if (!Directory.Exists(Path.GetDirectoryName(path)))
        {
            Directory.CreateDirectory(Path.GetDirectoryName(path));
        }

        try
        {
            File.WriteAllBytes(path, imageBytes);
            Debug.Log("Saved Data to: " + path.Replace("/", "\\"));
        }
        catch (Exception e)
        {
            Debug.LogWarning("Failed To Save Data to: " + path.Replace("/", "\\"));
            Debug.LogWarning("Error: " + e.Message);
        }
    }

    byte[] loadImage(string path)
    {
        byte[] dataByte = null;

        //Exit if Directory or File does not exist
        if (!Directory.Exists(Path.GetDirectoryName(path)))
        {
            Debug.LogWarning("Directory does not exist");
            return null;
        }

        if (!File.Exists(path))
        {
            Debug.Log("File does not exist");
            return null;
        }

        try
        {
            dataByte = File.ReadAllBytes(path);
            Debug.Log("Loaded Data from: " + path.Replace("/", "\\"));
        }
        catch (Exception e)
        {
            Debug.LogWarning("Failed To Load Data from: " + path.Replace("/", "\\"));
            Debug.LogWarning("Error: " + e.Message);
        }

        return dataByte;
    }
}