1 /*
2 * Copyright (C) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "file_utils.h"
17
18 #include <fcntl.h>
19 #include <sys/sendfile.h>
20 #include <sys/stat.h>
21
22 #include "media_log.h"
23 #include "media_file_utils.h"
24 #include "moving_photo_file_utils.h"
25 #include "database_adapter.h"
26 #include "dfx_utils.h"
27 #include "result_set_utils.h"
28 #include "media_column.h"
29 #include "image_packer.h"
30 #include "medialibrary_errno.h"
31 #include "medialibrary_tracer.h"
32 #include "medialibrary_type_const.h"
33 #include "medialibrary_operation.h"
34 #include "medialibrary_object_utils.h"
35 #include "picture.h"
36 #include "image_type.h"
37
38 using namespace std;
39
40 namespace OHOS {
41 namespace Media {
42 const uint8_t PACKOPTION_QUALITY = 95;
FileUtils()43 FileUtils::FileUtils() {}
44
~FileUtils()45 FileUtils::~FileUtils() {}
46
DeleteFile(const string & fileName)47 int FileUtils::DeleteFile(const string &fileName)
48 {
49 int ret = remove(fileName.c_str());
50 if (ret < 0) {
51 MEDIA_ERR_LOG("DeleteFile fail, ret: %{public}d, errno: %{public}d", ret, errno);
52 }
53 return ret;
54 }
55
IsFileExist(const string & fileName)56 bool FileUtils::IsFileExist(const string &fileName)
57 {
58 struct stat statInfo {};
59 return ((stat(fileName.c_str(), &statInfo)) == E_SUCCESS);
60 }
61
SaveImage(const string & filePath,void * output,size_t writeSize)62 int32_t FileUtils::SaveImage(const string &filePath, void *output, size_t writeSize)
63 {
64 const mode_t fileMode = 0644;
65 MediaLibraryTracer tracer;
66 tracer.Start("FileUtils::SaveImage");
67 string filePathTemp = filePath + ".high";
68 int fd = open(filePathTemp.c_str(), O_CREAT|O_WRONLY|O_TRUNC, fileMode);
69 if (fd < 0) {
70 MEDIA_ERR_LOG("fd.Get() < 0 fd %{public}d errno: %{public}d", fd, errno);
71 return E_ERR;
72 }
73 MEDIA_DEBUG_LOG("filePath: %{private}s, fd: %{public}d", filePath.c_str(), fd);
74
75 int ret = write(fd, output, writeSize);
76 close(fd);
77 if (ret < 0) {
78 MEDIA_ERR_LOG("write fail, ret: %{public}d, errno: %{public}d", ret, errno);
79 DeleteFile(filePathTemp);
80 return ret;
81 }
82
83 ret = rename(filePathTemp.c_str(), filePath.c_str());
84 if (ret < 0) {
85 MEDIA_ERR_LOG("rename fail, ret: %{public}d, errno: %{public}d", ret, errno);
86 DeleteFile(filePathTemp);
87 return ret;
88 }
89
90 return ret;
91 }
92
SavePicture(const string & imageId,std::shared_ptr<Media::Picture> & picture,bool isEdited,bool isLowQualityPicture)93 int32_t FileUtils::SavePicture(const string &imageId, std::shared_ptr<Media::Picture> &picture,
94 bool isEdited, bool isLowQualityPicture)
95 {
96 MediaLibraryTracer tracer;
97 // 通过imageid获取fileid 获取uri
98 if (picture == nullptr) {
99 return -1;
100 }
101 MEDIA_INFO_LOG("photoid: %{public}s", imageId.c_str());
102 MediaLibraryCommand cmd(OperationObject::FILESYSTEM_PHOTO, OperationType::QUERY);
103 string where = PhotoColumn::PHOTO_ID + " = ? ";
104 vector<string> whereArgs { imageId };
105 cmd.GetAbsRdbPredicates()->SetWhereClause(where);
106 cmd.GetAbsRdbPredicates()->SetWhereArgs(whereArgs);
107 vector<string> columns { MediaColumn::MEDIA_ID, MediaColumn::MEDIA_FILE_PATH, PhotoColumn::PHOTO_EDIT_TIME,
108 PhotoColumn::PHOTO_SUBTYPE, MediaColumn::MEDIA_MIME_TYPE};
109 tracer.Start("Query");
110 auto resultSet = DatabaseAdapter::Query(cmd, columns);
111 if (resultSet == nullptr || resultSet->GoToFirstRow() != E_OK) {
112 tracer.Finish();
113 MEDIA_INFO_LOG("result set is empty");
114 return -1;
115 }
116 tracer.Finish();
117 string path = GetStringVal(MediaColumn::MEDIA_FILE_PATH, resultSet);
118 int fileId = GetInt32Val(MediaColumn::MEDIA_ID, resultSet);
119 string sourcePath = isEdited ? MediaLibraryAssetOperations::GetEditDataSourcePath(path) : path;
120 //查询是否编辑 编辑目录下
121 string mime_type = GetStringVal(MediaColumn::MEDIA_MIME_TYPE, resultSet);
122 resultSet->Close();
123 if (mime_type == "") {
124 mime_type = "image/jpeg";
125 }
126 size_t sizeHeic = -1;
127 size_t pos = sourcePath.find_last_of('.');
128 string pathPos = sourcePath.substr(0, pos);
129 string pathHeic = pathPos + ".heic";
130 MediaFileUtils::GetFileSize(pathHeic, sizeHeic);
131 size_t sizeJpeg = -1;
132 string pathJpeg = pathPos + ".jpeg";
133 MediaFileUtils::GetFileSize(pathJpeg, sizeJpeg);
134
135 if (isLowQualityPicture && (sizeHeic > 0 || sizeJpeg > 0)) {
136 return -1;
137 }
138
139 int ret = DealPicture(mime_type, sourcePath, picture, !isLowQualityPicture);
140 return ret;
141 }
142
SavePicture(const string & path,std::shared_ptr<Media::Picture> & picture,const std::string & mime_type,bool isHighQualityPicture)143 int32_t FileUtils::SavePicture(const string &path, std::shared_ptr<Media::Picture> &picture,
144 const std::string &mime_type, bool isHighQualityPicture)
145 {
146 MEDIA_INFO_LOG("SavePicture width %{public}d, heigh %{public}d, mime_type %{public}sd",
147 picture->GetMainPixel()->GetWidth(), picture->GetMainPixel()->GetHeight(), mime_type.c_str());
148 return DealPicture(mime_type, path, picture, isHighQualityPicture);
149 }
150
DealPicture(const std::string & mime_type,const std::string & path,std::shared_ptr<Media::Picture> & picture,bool isHighQualityPicture)151 int32_t FileUtils::DealPicture(const std::string &mime_type, const std::string &path,
152 std::shared_ptr<Media::Picture> &picture, bool isHighQualityPicture)
153 {
154 MediaLibraryTracer tracer;
155 tracer.Start("FileUtils::DealPicture");
156 MEDIA_INFO_LOG("DealPicture, path: %{public}s, mime_type: %{public}s",
157 MediaFileUtils::DesensitizePath(path).c_str(), mime_type.c_str());
158 if (picture == nullptr) {
159 MEDIA_ERR_LOG("picture is nullptr.");
160 return -1;
161 }
162 Media::ImagePacker imagePacker;
163 Media::PackOption packOption;
164 packOption.format = mime_type;
165 packOption.needsPackProperties = true;
166 packOption.desiredDynamicRange = EncodeDynamicRange::AUTO;
167 packOption.isEditScene = false;
168 packOption.quality = PACKOPTION_QUALITY;
169 size_t lastSlash = path.rfind('/');
170 CHECK_AND_RETURN_RET_LOG(lastSlash != string::npos && path.size() > (lastSlash + 1), E_INVALID_VALUES,
171 "Failed to check outputPath: %{public}s", path.c_str());
172 string tempInternal = isHighQualityPicture ? "high_" :"low_";
173 string tempOutputPath = path.substr(0, lastSlash + 1) + tempInternal + path.substr(lastSlash + 1);
174 int32_t ret = MediaFileUtils::CreateAsset(tempOutputPath);
175 CHECK_AND_RETURN_RET_LOG(ret == E_SUCCESS, E_HAS_FS_ERROR,
176 "Failed to create temp filters file %{private}s", tempOutputPath.c_str());
177 imagePacker.StartPacking(tempOutputPath, packOption);
178 imagePacker.AddPicture(*(picture));
179 imagePacker.FinalizePacking();
180 size_t size = -1;
181 MediaFileUtils::GetFileSize(tempOutputPath, size);
182 MEDIA_INFO_LOG("SavePicture end size: %{public}zu", size);
183 if (size == 0) {
184 CHECK_AND_PRINT_LOG(MediaFileUtils::DeleteFile(tempOutputPath),
185 "Failed to delete temp filters file, errno: %{public}d", errno);
186 return E_OK;
187 }
188 ret = rename(tempOutputPath.c_str(), path.c_str());
189 CHECK_AND_PRINT_LOG(ret == E_SUCCESS, "Failed rename errno: %{public}d", errno);
190 if (MediaFileUtils::IsFileExists(tempOutputPath)) {
191 MEDIA_INFO_LOG("file: %{public}s exists and needs to be deleted", tempOutputPath.c_str());
192 if (!MediaFileUtils::DeleteFile(tempOutputPath)) {
193 MEDIA_ERR_LOG("delete file: %{public}s failed", tempOutputPath.c_str());
194 }
195 }
196 return ret;
197 }
198
SaveVideo(const std::string & filePath,bool isEdited)199 int32_t FileUtils::SaveVideo(const std::string &filePath, bool isEdited)
200 {
201 string tempPath = filePath.substr(0, filePath.rfind('.')) + "_tmp" + filePath.substr(filePath.rfind('.'));
202 string targetPath = filePath;
203 if (isEdited) {
204 targetPath = MediaLibraryAssetOperations::GetEditDataSourcePath(filePath);
205 }
206
207 if (!IsFileExist(tempPath)) {
208 MEDIA_ERR_LOG("file not exist: %{public}s", DfxUtils::GetSafePath(tempPath).c_str());
209 }
210
211 if (!IsFileExist(targetPath)) {
212 MEDIA_ERR_LOG("file not exist: %{public}s", DfxUtils::GetSafePath(filePath).c_str());
213 }
214
215 MEDIA_INFO_LOG("video rename targetPath: %{public}s, tempPath: %{public}s",
216 DfxUtils::GetSafePath(targetPath).c_str(), DfxUtils::GetSafePath(tempPath).c_str());
217 return rename(tempPath.c_str(), targetPath.c_str());
218 }
219
SaveMovingPhotoVideo(const std::string & filePath,bool isEdited,bool isMovingPhotoEffectMode)220 int32_t FileUtils::SaveMovingPhotoVideo(const std::string &filePath, bool isEdited, bool isMovingPhotoEffectMode)
221 {
222 string tempPath = MovingPhotoFileUtils::GetMovingPhotoVideoPath(
223 filePath.substr(0, filePath.rfind('.')) + "_tmp" + filePath.substr(filePath.rfind('.')));
224 string targetPath;
225
226 string videoPath = MovingPhotoFileUtils::GetMovingPhotoVideoPath(filePath);
227 string sourceVideoPath = MovingPhotoFileUtils::GetMovingPhotoVideoPath(
228 MediaLibraryAssetOperations::GetEditDataSourcePath(filePath));
229
230 if (!IsFileExist(tempPath)) {
231 MEDIA_ERR_LOG("file not exist: %{public}s", DfxUtils::GetSafePath(tempPath).c_str());
232 return E_ERR;
233 }
234
235 if (IsFileExist(sourceVideoPath)) {
236 targetPath = sourceVideoPath;
237 } else if (IsFileExist(videoPath)) {
238 targetPath = videoPath;
239 } else {
240 MEDIA_ERR_LOG("file not exist: %{public}s", DfxUtils::GetSafePath(filePath).c_str());
241 return E_ERR;
242 }
243
244 MEDIA_INFO_LOG("video rename targetPath: %{public}s, tempPath: %{public}s",
245 DfxUtils::GetSafePath(targetPath).c_str(), DfxUtils::GetSafePath(tempPath).c_str());
246
247 int32_t ret = rename(tempPath.c_str(), targetPath.c_str());
248 if (ret != E_OK) {
249 MEDIA_ERR_LOG("video rename failed, errno: %{public}d", errno);
250 return ret;
251 }
252
253 string editDataCameraPath = PhotoFileUtils::GetEditDataCameraPath(filePath);
254 if (!isEdited && !isMovingPhotoEffectMode && IsFileExist(editDataCameraPath) && IsFileExist(sourceVideoPath)) {
255 ret = MediaLibraryPhotoOperations::AddFiltersToVideoExecute(filePath, false, true);
256 MEDIA_INFO_LOG("MediaLibraryPhotoOperations AddFiltersToVideoExecute ret: %{public}d", ret);
257 }
258 MEDIA_INFO_LOG("SaveMovingPhotoVideo end ret: %{public}d", ret);
259 return ret;
260 }
261
DeleteTempVideoFile(const std::string & filePath)262 int32_t FileUtils::DeleteTempVideoFile(const std::string &filePath)
263 {
264 MEDIA_INFO_LOG("filePath: %{public}s", filePath.c_str());
265 string tempPath = filePath.substr(0, filePath.rfind('.')) + "_tmp" + filePath.substr(filePath.rfind('.'));
266 if (IsFileExist(tempPath)) {
267 return DeleteFile(tempPath);
268 }
269 return E_OK;
270 }
271 } // namespace Media
272 } // namespace OHOS