【问题标题】:Problem with downloading image and displaying it下载图像并显示问题
【发布时间】:2021-10-02 06:05:24
【问题描述】:

当我点击一张图片时,它会下载并存储在一个特殊的文件夹中,然后在 Gallery App 中打开它。但是它第一次发现错误,第二次点击它:它显示正确......

我该如何解决这个问题?

查看视频了解说明。

Video (it's a gif)

下载图片的代码。

public async Task DownloadImage(string URL)
{
    WebClient webClient = new WebClient();

    string folderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "Images", "temp");
    string fileName = URL.ToString().Split('/').Last();
    string filePath = Path.Combine(folderPath + "/", fileName);

    webClient.DownloadDataCompleted += (s, e) =>
    {
        byte[] bytes = new byte[e.Result.Length];
        bytes = e.Result; // get the downloaded data
        File.WriteAllBytes(filePath, bytes);
    };

    webClient.DownloadDataAsync(new Uri(URL));

    Preferences.Set("filePath", filePath);
}

上面的代码执行函数:

Image imagen = new Image
{
                    Source = url + Foto.ID_Parte + "/" + Foto.Archivo
};
var imagen_tap = new TapGestureRecognizer();
imagen_tap.Tapped += async (s, e) =>
{
    string urlImage = url + Foto.ID_Parte + "/" + Foto.Archivo;
    await api.DownloadImage(urlImage);
    string path = Preferences.Get("filePath", "");
    try
    {
        await Launcher.OpenAsync(new OpenFileRequest { File = new ReadOnlyFile(path) });
    }
    catch
    {
        await DisplayAlert("Error", "No se ha encontrado la imagen:" + path, "Cerrar");
    }
};
                
imagen.GestureRecognizers.Add(imagen_tap);

编辑: 例外给出:

EXCEPTION:::::: System.IO.FileNotFoundException: Could not find file "/data/user/0/com.companyname.workersapp/files/Images/temp/2021072010242814266200.jpg"
File name: '/data/user/0/com.companyname.workersapp/files/Images/temp/2021072010242814266200.jpg'
  at System.IO.FileStream..ctor (System.String path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, System.Int32 bufferSize, System.Boolean anonymous, System.IO.FileOptions options) [0x001aa] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/mcs/class/corlib/System.IO/FileStream.cs:239 
  at System.IO.FileStream..ctor (System.String path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, System.Int32 bufferSize, System.IO.FileOptions options) [0x00000] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/mcs/class/corlib/System.IO/FileStream.cs:106 
  at (wrapper remoting-invoke-with-check) System.IO.FileStream..ctor(string,System.IO.FileMode,System.IO.FileAccess,System.IO.FileShare,int,System.IO.FileOptions)
  at System.IO.FileSystem.CopyFil07-26 12:42:47.751 V/mono-stdout(22224):   at System.IO.FileSystem.CopyFile (System.String sourceFullPath, System.String destFullPath, System.Boolean overwrite) [0x00025] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/System.IO.FileSystem/src/System/IO/FileSystem.Unix.cs:54 
  at System.IO.File.Copy (System.String sourceFileName, System.String destFileName, System.Boolean overwrite) [0x00056] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/System.IO.FileSystem/src/System/IO/File.cs:74 
  at Xamarin.Essentials.Platform.GetShareableFileUri (Xamarin.Essentials.FileBase file) [0x0002c] in D:\a\1\s\Xamarin.Essentials\Platform\Platform.android.cs:107-26 12:42:47.752 V/mono-stdout(22224):   at Xamarin.Essentials.Platform.GetShareableFileUri (Xamarin.Essentials.FileBase file) [0x0002c] in D:\a\1\s\Xamarin.Essentials\Platform\Platform.android.cs:151 
  at Xamarin.Essentials.Launcher.PlatformOpenAsync (Xamarin.Essentials.OpenFileRequest request) [0x00000] in D:\a\1\s\Xamarin.Essentials\Launcher\Launcher.android.cs:41 
  at Xamarin.Essentials.Launcher.OpenAsync (Xamarin.Essentials.OpenFileRequest request) [0x00021] in D:\a\1\s\Xamarin.Essentials\Launcher\Launcher.shared.cs:50 
  at WorkersApp.Pageviews.DatosParte+<>c__DisplayClass16_0.<.ctor>b__3 (System.Object s, System.EventArgs e) [0x00110] in C:\Users\CGarcia\source\repos\WorkersApp\WorkersApp\WorkersApp\Pageviews\DatosParte.xaml.cs:101 

第 101 行是:

await Launcher.OpenAsync(new OpenFileRequest { File = new ReadOnlyFile(path) });

【问题讨论】:

  • 为什么不早点下载图片
  • 嗯,我可以试试。我想点击下载图像,因为您并不总是会看到图像。但这是一个可能的解决办法。
  • 捕获的错误是什么?
  • 我编辑了添加异常的问题。问候和感谢!
  • DownloadDataAsync 是异步的,所以它在完成下载之前就返回了。

标签: android ios image asynchronous xamarin.forms


【解决方案1】:

原因

DownloadDataAsync是同步方法,它通过回调DownloadDataCompleted返回数据,所以当你第一次点击图片时,它会打开没有完全下载的文件。

解决方案

  1. DownloadDataAsync替换为DownloadDataTaskAsync,在这种情况下我们不需要DownloadDataCompleted,该方法将返回数据。
public async Task DownloadImage(string URL)
{
    WebClient webClient = new WebClient();

    string folderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "Images", "temp");
    string fileName = URL.ToString().Split('/').Last();
    string filePath = Path.Combine(folderPath + "/", fileName);

    Preferences.Set("filePath", filePath);

    byte[] bytes = await webClient.DownloadDataTaskAsync(new Uri(""));
    File.WriteAllBytes(filePath, bytes);
  
}
  1. 将逻辑(打开文件)放入DownloadDataCompleted,这样可以保证文件下载完整。
public void DownloadImage(string URL)
{
    WebClient webClient = new WebClient();

    string folderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "Images", "temp");
    string fileName = URL.ToString().Split('/').Last();
    string filePath = Path.Combine(folderPath + "/", fileName);

    webClient.DownloadDataCompleted += (s, e) =>
    {
        byte[] bytes = new byte[e.Result.Length];
        bytes = e.Result; // get the downloaded data
        File.WriteAllBytes(filePath, bytes);

        //move to here
        await Launcher.OpenAsync(new OpenFileRequest { File = new ReadOnlyFile(filePath ) });

    };

    webClient.DownloadDataAsync(new Uri(URL));
}


imagen_tap.Tapped += (s, e) =>
{
    string urlImage = url + Foto.ID_Parte + "/" + Foto.Archivo;
    api.DownloadImage(urlImage);
};

个人比较推荐第二种方式。

【讨论】:

  • 做到了。你真棒。我用的是第二种方式,第一种给宿主带来了一些麻烦(不知道为什么,不想研究)
【解决方案2】:

不知怎的,我能理解您的问题...第一次下载图像时出现问题会导致错误。我已经使用内容解析器完成了图像的下载。可能对你有帮助

`
私人乐趣 saveImage(bmp: Bitmap) {

    var imageOutStream: OutputStream
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        val values = ContentValues()
        //image name
        values.put(MediaStore.Images.Media.DISPLAY_NAME, "image.jpg");
        // image type
        values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
        //storage path
        values.put(MediaStore.Images.Media.RELATIVE_PATH, "DCIM/" + "Camera");

        val uri = requireContext().contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
        imageOutStream = uri?.let { requireContext().getContentResolver().openOutputStream(it) }!!
    }

    else
    {
        //creating directory and saving
        val imagesDir =
            Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString()
        val image = File(imagesDir, "image.jpg")
        imageOutStream =  FileOutputStream(image);

    }
    //compreesing the image
    bmp.compress(Bitmap.CompressFormat.JPEG, 100, imageOutStream);
    Toast.makeText(requireContext(),"ImageSaved",Toast.LENGTH_LONG).show()
    imageOutStream.close();

}`

【讨论】:

  • 我不明白...什么是私人乐趣?但是,是的,问题是第一次点击导致异常,第二次成功。
  • 其实它是一种 kotlin 语言,两者之间没有太大区别。 fun 是我们调用的函数和“val” - 变量声明
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-20
  • 1970-01-01
  • 2011-09-09
  • 1970-01-01
相关资源
最近更新 更多