从在线资源统一将图像保存在移动设备上

Save images on mobile from online source unity

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

我有在线图像,我从 json 文件中提取了 url,现在我想将它们存储在本地移动设备上,以节省最终用户的数据传输。

我在持久数据路径和 IO.directories 上兜了一圈,不断遇到问题。

目前我有一个函数可以从网上保存文本并成功将其存储在设备上但是如果我将它用于图像它不会工作由于下面显示的字符串参数,我尝试转换它也对字节编辑函数而不是传递它 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 点,我无法弄清楚,各位大侠能帮帮我吗?提前致谢。

I tried to convert it to bytes editing the function too rather than passing it www.text and got an image corrupt error

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

1。使用 WWW.bytes 而不是 WWW.text 下载图像或文件。

2.用File.WriteAllBytes.

保存图片

3.用File.ReadAllBytes读图.

4。使用 Texture2D.LoadImage(yourImageByteArray);

将图像加载到纹理

5。如果您希望它与每个平台兼容,您的路径必须是 Application.persistentDataPath/yourfolderName/thenFileName不应该Application.persistentDataPath/yourFileNameApplication.dataPath

6。最后,使用 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;
}

用法:

准备 url 下载图像并保存到:

//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");

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

下载文件:

downloadImage(url, savePath);

从文件加载图像:

byte[] imageBytes = loadImage(savePath);

将图像放入 Texture2D:

Texture2D texture;
texture = new Texture2D(2, 2);
texture.LoadImage(imageBytes);

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

WWW 已过时

The UnityWebRequest is a replacement for Unity’s original WWW object. It provides a modular system for composing HTTP requests and handling HTTP responses. The primary goal of the UnityWebRequest system is to permit Unity games to interact with modern Web backends. It also supports high-demand features such as chunked HTTP requests, streaming POST/PUT operations and full control over HTTP headers and verbs. https://docs.huihoo.com/unity/5.4/Documentation/en/Manual/UnityWebRequest.html

UnityWebRequest.GetTexture 已过时

Note: UnityWebRequest.GetTexture is obsolete. Use UnityWebRequestTexture.GetTexture instead.

Note: Only JPG and PNG formats are supported.

UnityWebRequest properly configured to download an image and convert it to a 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;
    }
}