这段代码直到几天前都运行良好。然而,我们注意到下载 40 个文件后就失败了。我不记得最近更改过任何配置参数。
尝试通过验证这些场景进行隔离:
令人费解的是 - 为什么在第 40 个文件之后下载失败?客户端(浏览器)收到错误“无法下载 zip 文件。如果问题仍然存在,请使用高速互联网连接重试或联系支持人员!”。这是从 catch 块返回给客户端的响应。
当然,这个错误是可以修复的。但是,即使有更多文件,它也无法帮助用户下载超过 40 个文件。
我已经失去理智了。非常感谢任何帮助。
下面是经过净化的代码:
public function downloadZip(Request $request) {
$reqdata = $request->all();
$ordref = @$reqdata['ordref'];
$usrnumber = @$reqdata['usrnumber'];
if (!$ordref || !$usrnumber) {
//check if parameters passed valid
echo json_encode($data);
exit();
}
$this->db = DB::table("orders AS o");
$details = $this->db->select("o.photos", "o.ref", "o.id", "o.folder_id", "o.price","o.is_download")
->where(....)
->first();
if (!$details) {
return redirect("/");
}
//check if json is valid
$images = $this->processphotos($details->photos);
// find photo ids from DB
....
....
$dbimages = $this->getimagesbyids($imageids);
$imageNames = [];
foreach ($dbimages as $item) {
$thumbName = $item->imgurl;
array_push($imageNames, array('image' => $thumbName, 'category' => $item->category, 'id' => $item->id));
}
if (!$imageNames) {
//return No images found error.
}
$zipimages = [];
$public_dir = public_path() . DIRECTORY_SEPARATOR . 'downloads' . DIRECTORY_SEPARATOR;
$zipimagesarray = array();
$imagepatharray = explode("/", $imageNames[0]['image']);
$imagename = end($imagepatharray);
$ctr = 100;
foreach ($imageNames as $row) {
$imgtype = 'jpg';
$prefix = $usrnumber.'_';
$imagename = $prefix . $ctr . $imgtype;
$signedurl = $this->getpresignedurl($row['image']);
@ File::copy($signedurl, $public_dir . $imagename);
array_push($zipimagesarray, array('path' => $public_dir, "image" => $imagename));
$ctr++;
}
$imageZip = [];
$certZip = [];
foreach ($zipimagesarray as $imagePublic) {
$path = explode(DIRECTORY_SEPARATOR,$imagePublic['path']);
$zipImage = $imagePublic['path'] . $imagePublic['image'];
array_push($imageZip, $zipImage);
}
try {
$zipName = $usrnumber . date('G:i:s') . ".zip";
Zipper::make(public_path('downloadOrder/' . $zipName))->add($imageZip)->close();
File::delete($imageZip);
$file = "/download/" . $zipName;
$data['result'] = array();
$data['result'] = url('/') . $file ;
$data['statusCode'] = 200;
$data['hasError'] = false;
$data['message'] = "Images retrieval is successful.";
return response($data)->header('Content-Type', 'application/json');
} catch (\Exception $ex) {
$data['result'] = array();
$data['statusCode'] = 400;
$data['hasError'] = true;
$data['message'] = "Unable to download the zip file. Please retry on a high speed internet connection or contact support, if issue persists!";
Log::error("Api::downloadZip - orderId: " . $data['Message'] . " " . $ex->getMessage());
return response($data)->header('Content-Type', 'application/json');
}
}
和
function getpresignedurl($key, $s3Client = null) {
$s3_env = [];
$Bucket = "xxxxx";
if (is_null($s3Client)) {
$s3_env = array('region' => config('aws.AWS_REGION'),
'credentials' => ['key' => config('aws.AWS_ACCESS_KEY_ID'), 'secret' => config('aws.AWS_SECRET_ACCESS_KEY')]);
$s3Client = \App::make('aws')->createClient('s3', $s3_env);
}
//Creating a presigned URL
$cmd = $s3Client->getCommand('GetObject', [
'Bucket' => $Bucket,
'Key' => $key
]);
$request = $s3Client->createPresignedRequest($cmd, '+30 minutes');
$signedurl = (string) $request->getUri();
return $signedurl;
}
嗯,这不是所报告问题的确切解决方案。
我已经通过实施全新的方法来解决这个问题。引入了新方法
downloadFile
并使用 AWS SDK GetObject
命令下载文件。即使 saveAs
中的 GetObject
参数也无法解决问题。此解决方案 getObject with SaveAs 在 sdk v3 中不起作用 有帮助。
function downloadFile($key, $destination, $s3Client = null) {
$s3_env = [];
$Bucket = "xxxxx";
try {
if (is_null($s3Client)) {
$s3_env = array('region' => config('aws.AWS_REGION'),
'credentials' => ['key' => config('aws.AWS_ACCESS_KEY_ID'), 'secret' => config('aws.AWS_SECRET_ACCESS_KEY')]);
$s3Client = \App::make('aws')->createClient('s3', $s3_env);
}
//Creating a presigned URL
$cmd = $s3Client->getCommand('GetObject', [
'Bucket' => $Bucket,
'Key' => $key,
'@http' => ['sink' => $destination]
]);
$result = $s3Client->execute($cmd);
if ($result['@metadata']['statusCode'] === 200) {
return true;
} else {
Log::error("Api::downloadFile - Failed to download to $destination " . $result['@metadata']['statusCode']);
return false;
}
} catch (\Exception $ex) {
Log::error("Api::downloadFile - exception: $ex->getMessage()");
return false;
}
}
并在主方法
downloadZip
中,替换了这些行
$signedurl = $this->getpresignedurl($row['image']);
@ File::copy($signedurl, $public_dir . $imagename);
与
$destination = $public_dir . $imagename;
$result = $this->downloadFile($row['image'], $destination);
此外,为了处理下载失败,添加了一个
if
条件
if (file_exists($public_dir . $imagename) {
array_push($zipimagesarray, array('path' => $public_dir, "image" => $imagename));
}
如果有人可以提供关于为什么在第 40 个文件之后发生自动 html 编码的解决方案,我会再等几天,然后接受此解决方案。