我试图将一些图片上传到我的FTP表格中。它在我的华为P20上工作得很好,但据报道,在内存较少的手机上,当他们试图上传更大的图片时,应用会冻结。
在图片选择(最多4张)后,我调整图像大小并压缩它们以减小尺寸,但没有运气
码:
public static byte[] RotateImage(string path)
{
byte[] imageBytes;
var originalImage = BitmapFactory.DecodeFile(path);
var rotation = GetRotation(path);
//Width 3000 Height 4000
var width = (originalImage.Width * 0.25);
var height = (originalImage.Height * 0.25);
if(originalImage.Height>2400)
{
width = (originalImage.Width * 0.20);
height = (originalImage.Height * 0.20);
}
if (originalImage.Height < 600)
{
width = (originalImage.Width * 0.80);
height = (originalImage.Height * 0.80);
}
var scaledImage = Bitmap.CreateScaledBitmap(originalImage, (int)width, (int)height, true);
Bitmap rotatedImage = scaledImage;
if (rotation != 0)
{
var matrix = new Matrix();
matrix.PostRotate(rotation);
rotatedImage = Bitmap.CreateBitmap(scaledImage, 0, 0, scaledImage.Width, scaledImage.Height, matrix, true);
scaledImage.Recycle();
scaledImage.Dispose();
}
using (var ms = new MemoryStream())
{
if (rotatedImage.Width > 1000 || rotatedImage.Height > 1000)
{
rotatedImage.Compress(Bitmap.CompressFormat.Jpeg, 30, ms);
}
if (rotatedImage.Width < 500 || rotatedImage.Height < 500)
{
rotatedImage.Compress(Bitmap.CompressFormat.Jpeg, 60, ms);
}
if (rotatedImage.Width <= 1000 && rotatedImage.Width >= 500)
{
rotatedImage.Compress(Bitmap.CompressFormat.Jpeg, 45, ms);
}
imageBytes = ms.ToArray();
}
originalImage.Recycle();
rotatedImage.Recycle();
originalImage.Dispose();
rotatedImage.Dispose();
GC.Collect();
return imageBytes;
}
然后我将它们发送到MessagingCenter并在PCL中检索它们。当我尝试将其上传到FTP时,应用程序冻结
PCL中的代码:
for (int i = 0; i < _images.Count; i++)
{
DependencyService.Get<IFtpWebRequest>().upload("FTP", _images[i], "SITE", "PASSWORD", "DIRECTORY");
}
我正在调用的平台特定代码是:
public string upload(string FtpUrl, string fileName, string userName, string password, string UploadDirectory = "")
{
try
{
WebRequest request = WebRequest.Create(FtpUrl+UploadDirectory);
request.Method = WebRequestMethods.Ftp.MakeDirectory;
request.Credentials = new NetworkCredential(userName, password);
using (var resp = (FtpWebResponse)request.GetResponse())
{
}
}
catch(Exception e) { }
try
{
string PureFileName = new FileInfo(fileName).Name;
String uploadUrl = String.Format("{0}{1}/{2}", FtpUrl, UploadDirectory, PureFileName);
FtpWebRequest req = (FtpWebRequest)FtpWebRequest.Create(uploadUrl);
req.Proxy = null;
req.Method = WebRequestMethods.Ftp.UploadFile;
req.Credentials = new NetworkCredential(userName, password);
req.UseBinary = true;
req.UsePassive = true;
byte[] data = File.ReadAllBytes(fileName);
req.ContentLength = data.Length;
Stream stream = req.GetRequestStream();
stream.Write(data, 0, data.Length);
stream.Close();
FtpWebResponse res = (FtpWebResponse)req.GetResponse();
return res.StatusDescription;
}
catch (Exception err)
{
return err.ToString();
}
}
预期的结果应该是应用程序不会在任何手机上冻结。我能做些什么来阻止它?进一步增加压缩不是最佳解决方案,因为有些手机上传它没有问题,因此我可以实现更高的质量。
编辑:当一张大图片上传到FTP时,我检查了FTP上的图片,它上传了1/10的图片,其余为空白
EDIT2:将函数移动到另一个线程不再冻结应用程序,但仍然只有部分iamge上传到内存较少的设备上,我如何以某种方式强制整个图像上传?
将大图片上传到FTP时,我检查FTP上的图片,上传的图片的1/10,其余为空白
如果上传的图像非常大,那么这将是一个耗时的操作。如果将它放在主UI线程中,它将消耗大量内存和时间。当手机的内存很大时,它可能可以完成任务,但是当手机不大时,就会出现问题。
您需要将upload方法移动到后台线程,然后它不会影响UI线程。
如果在Android中,请尝试使用任务:
public async Task<string> upload(string FtpUrl, string fileName, string userName, string password, string UploadDirectory = "")
{
await Task.Run(() =>
{
try
{
WebRequest request = WebRequest.Create(FtpUrl+UploadDirectory);
request.Method = WebRequestMethods.Ftp.MakeDirectory;
request.Credentials = new NetworkCredential(userName, password);
using (var resp = (FtpWebResponse)request.GetResponse())
{
}
}
catch(Exception e) { }
...
});
}