• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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