Download files via FTP on Android
Asked Answered
B

2

2

I need to make a connection with a local FTP protocol between a computer (server) and my Android device (client). This should download files (images, OBJ,...) to be used in the Android Unity app scene. I've used WWW class to create this connection and it works fine in the Unity player run in another computer as client. Once I've exported the same scene as Android apk it didn't work (I'm sure that FTP connection is stable and it works because I'm able to access to the files from the browser). Does anybody know if there is another way or there are problems in my code to use the FTP protocol on Android Unity app? (the client doesn't need any authorisation and the authentication is anonymous) Here is the code I use to download one image inside the scene and render it as a sprite.

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 using System.Net;
 using System.IO;

 public class ClientFTP : MonoBehaviour
 {
   public UnityEngine.UI.Image label;

   IEnumerator Start ()
   {
       // Create the connection and whait until it is established
       string url = ("ftp://192.168.10.11/prova.png");
       WWW ftpconnection = new WWW (url);
       yield return ftpconnection;
       // Download the image and render it as a texture
       Texture2D tex = new Texture2D (250, 192);
       ftpconnection.LoadImageIntoTexture (tex);
       // Assign the texture to a new sprite
       Sprite s = Sprite.Create (tex, new Rect (0, 0, 250f, 192f), new Vector2 (0.5f, 0.5f), 300);
       label.preserveAspect = true;
       label.sprite = s;

    }
 }
Bouldin answered 14/4, 2017 at 12:27 Comment(1)
Yes, thank you! Now it worksBouldin
S
1

Why use FTP if you don't need Credential to access the files? You can just place the files in your server then access them with the WWW or UnityWebRequest API.

To answer your FTP question, WWW is not meant to be used with the FTP protocol. This is what the FtpWebRequest API is used for.

Below is a sample of FtpWebRequest.

private byte[] downloadWithFTP(string ftpUrl, string savePath = "", string userName = "", string password = "")
{
    FtpWebRequest request = (FtpWebRequest)WebRequest.Create(new Uri(ftpUrl));
    //request.Proxy = null;

    request.UsePassive = true;
    request.UseBinary = true;
    request.KeepAlive = true;

    //If username or password is NOT null then use Credential
    if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password))
    {
        request.Credentials = new NetworkCredential(userName, password);
    }

    request.Method = WebRequestMethods.Ftp.DownloadFile;

    //If savePath is NOT null, we want to save the file to path
    //If path is null, we just want to return the file as array
    if (!string.IsNullOrEmpty(savePath))
    {
        downloadAndSave(request.GetResponse(), savePath);
        return null;
    }
    else
    {
        return downloadAsbyteArray(request.GetResponse());
    }
}

byte[] downloadAsbyteArray(WebResponse request)
{
    using (Stream input = request.GetResponseStream())
    {
        byte[] buffer = new byte[16 * 1024];
        using (MemoryStream ms = new MemoryStream())
        {
            int read;
            while (input.CanRead && (read = input.Read(buffer, 0, buffer.Length)) > 0)
            {
                ms.Write(buffer, 0, read);
            }
            return ms.ToArray();
        }
    }
}

void downloadAndSave(WebResponse request, string savePath)
{
    Stream reader = request.GetResponseStream();

    //Create Directory if it does not exist
    if (!Directory.Exists(Path.GetDirectoryName(savePath)))
    {
        Directory.CreateDirectory(Path.GetDirectoryName(savePath));
    }

    FileStream fileStream = new FileStream(savePath, FileMode.Create);


    int bytesRead = 0;
    byte[] buffer = new byte[2048];

    while (true)
    {
        bytesRead = reader.Read(buffer, 0, buffer.Length);

        if (bytesRead == 0)
            break;

        fileStream.Write(buffer, 0, bytesRead);
    }
    fileStream.Close();
}

Usage:

Download and save(No Credential):

string path = Path.Combine(Application.persistentDataPath, "FTP Files");
path = Path.Combine(path, "data.png");
downloadWithFTP("ftp://yourUrl.com/yourFile", path);

Download and save(With Credential):

string path = Path.Combine(Application.persistentDataPath, "FTP Files");
path = Path.Combine(path, "data.png");
downloadWithFTP("ftp://yourUrl.com/yourFile", path, "UserName", "Password");

Download Only (No Credential):

string path = Path.Combine(Application.persistentDataPath, "FTP Files");
path = Path.Combine(path, "data.png");
byte[] yourImage = downloadWithFTP("ftp://yourUrl.com/yourFile", "");

//Convert to Sprite
Texture2D tex = new Texture2D(250, 192);
tex.LoadImage(yourImage);
Sprite s = Sprite.Create(tex, new Rect(0, 0, texture2D.width, texture2D.height), new Vector2(0.5f, 0.5f));

Download Only (With Credential):

string path = Path.Combine(Application.persistentDataPath, "FTP Files");
path = Path.Combine(path, "data.png");
byte[] yourImage = downloadWithFTP("ftp://yourUrl.com/yourFile", "", "UserName", "Password");

//Convert to Sprite
Texture2D tex = new Texture2D(250, 192);
tex.LoadImage(yourImage);
Sprite s = Sprite.Create(tex, new Rect(0, 0, texture2D.width, texture2D.height), new Vector2(0.5f, 0.5f));
Stereochromy answered 14/4, 2017 at 21:54 Comment(2)
I want to make loading bar and this code runs in main thread and blocks UI updating. How can I refactor it to make it run not in the main thread?Ricciardi
@Ricciardi Use UnityThread.executeInUpdate from my other postStereochromy
T
0
public boolean ftpDownloadVideo() {

String desFilePath = (Environment.getExternalStoragePublicDirectory(DIRECTORY_DOWNLOADS)).toString();    ///xet trong moi truong SD card////
        String srcFilePath = "/detect_disease/rice_detect_disease_2019_09_24__10_07_08.avi";
  boolean status = false;
        Log.d(TAG, "2");

        try {

                Log.e("downloadFTP login : ", "Success");
                OutputStream desFileStream = new BufferedOutputStream( new FileOutputStream(desFilePath));
                Log.d(TAG,"FileOutputStream");
                status = mFTPClient.retrieveFile(srcFilePath, desFileStream);
                Log.d(TAG, "4");
                desFileStream.close();

                Log.e("downloadFTP status : ", "" + status);
                Log.d(TAG, "5");
                return status;
        } catch (Exception e) {
            Log.d(TAG, "download failed");
        }
        return status;
    }
Tartrazine answered 3/10, 2019 at 7:4 Comment(2)
Welcome to Stack Overflow Tan Lee. However, this does not provide an answer to the question.You can search for similar questions, or refer to the related and linked questions on the right-hand side of the page to find an answer. If you have a related but different question, ask a new question, and include a link to this one to help provide context. See: Ask questions, get answers, no distractionsGonococcus
Please read above comment. Don't post question on answer section.Gonococcus

© 2022 - 2024 — McMap. All rights reserved.