• 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 {
FileUtils()42 FileUtils::FileUtils() {}
43 
~FileUtils()44 FileUtils::~FileUtils() {}
45 
DeleteFile(const string & fileName)46 int FileUtils::DeleteFile(const string &fileName)
47 {
48     int ret = remove(fileName.c_str());
49     if (ret < 0) {
50         MEDIA_ERR_LOG("DeleteFile fail, ret: %{public}d, errno: %{public}d", ret, errno);
51     }
52     return ret;
53 }
54 
IsFileExist(const string & fileName)55 bool FileUtils::IsFileExist(const string &fileName)
56 {
57     struct stat statInfo {};
58     return ((stat(fileName.c_str(), &statInfo)) == E_SUCCESS);
59 }
60 
SaveImage(const string & filePath,void * output,size_t writeSize)61 int32_t FileUtils::SaveImage(const string &filePath, void *output, size_t writeSize)
62 {
63     const mode_t fileMode = 0644;
64     MediaLibraryTracer tracer;
65     tracer.Start("FileUtils::SaveImage");
66     string filePathTemp = filePath + ".high";
67     int fd = open(filePathTemp.c_str(), O_CREAT|O_WRONLY|O_TRUNC, fileMode);
68     if (fd < 0) {
69         MEDIA_ERR_LOG("fd.Get() < 0 fd %{public}d errno: %{public}d", fd, errno);
70         return E_ERR;
71     }
72     MEDIA_DEBUG_LOG("filePath: %{private}s, fd: %{public}d", filePath.c_str(), fd);
73 
74     int ret = write(fd, output, writeSize);
75     close(fd);
76     if (ret < 0) {
77         MEDIA_ERR_LOG("write fail, ret: %{public}d, errno: %{public}d", ret, errno);
78         DeleteFile(filePathTemp);
79         return ret;
80     }
81 
82     ret = rename(filePathTemp.c_str(), filePath.c_str());
83     if (ret < 0) {
84         MEDIA_ERR_LOG("rename fail, ret: %{public}d, errno: %{public}d", ret, errno);
85         DeleteFile(filePathTemp);
86         return ret;
87     }
88 
89     return ret;
90 }
91 
SavePicture(const string & imageId,std::shared_ptr<Media::Picture> & picture,bool isEdited,bool isLowQualityPicture)92 int32_t FileUtils::SavePicture(const string &imageId, std::shared_ptr<Media::Picture> &picture,
93     bool isEdited, bool isLowQualityPicture)
94 {
95     MediaLibraryTracer tracer;
96     // 通过imageid获取fileid 获取uri
97     if (picture == nullptr) {
98         return -1;
99     }
100     MEDIA_INFO_LOG("photoid: %{public}s", imageId.c_str());
101     MediaLibraryCommand cmd(OperationObject::FILESYSTEM_PHOTO, OperationType::QUERY);
102     string where = PhotoColumn::PHOTO_ID + " = ? ";
103     vector<string> whereArgs { imageId };
104     cmd.GetAbsRdbPredicates()->SetWhereClause(where);
105     cmd.GetAbsRdbPredicates()->SetWhereArgs(whereArgs);
106     vector<string> columns { MediaColumn::MEDIA_ID, MediaColumn::MEDIA_FILE_PATH, PhotoColumn::PHOTO_EDIT_TIME,
107         PhotoColumn::PHOTO_SUBTYPE, MediaColumn::MEDIA_MIME_TYPE};
108     tracer.Start("Query");
109     auto resultSet = DatabaseAdapter::Query(cmd, columns);
110     if (resultSet == nullptr || resultSet->GoToFirstRow() != E_OK) {
111         tracer.Finish();
112         MEDIA_INFO_LOG("result set is empty");
113         return -1;
114     }
115     tracer.Finish();
116     string path = GetStringVal(MediaColumn::MEDIA_FILE_PATH, resultSet);
117     int fileId = GetInt32Val(MediaColumn::MEDIA_ID, resultSet);
118     string sourcePath = isEdited ? MediaLibraryAssetOperations::GetEditDataSourcePath(path) : path;
119     //查询是否编辑 编辑目录下
120     string mime_type = GetStringVal(MediaColumn::MEDIA_MIME_TYPE, resultSet);
121     resultSet->Close();
122     if (mime_type == "") {
123         mime_type = "image/jpeg";
124     }
125     size_t sizeHeic = -1;
126     size_t pos = sourcePath.find_last_of('.');
127     string pathPos = sourcePath.substr(0, pos);
128     string pathHeic = pathPos + ".heic";
129     MediaFileUtils::GetFileSize(pathHeic, sizeHeic);
130     size_t sizeJpeg = -1;
131     string pathJpeg = pathPos + ".jpeg";
132     MediaFileUtils::GetFileSize(pathJpeg, sizeJpeg);
133 
134     if (isLowQualityPicture && (sizeHeic > 0 || sizeJpeg > 0)) {
135         return -1;
136     }
137 
138     int ret = DealPicture(mime_type, sourcePath, picture);
139     return ret;
140 }
141 
SavePicture(const string & path,std::shared_ptr<Media::Picture> & picture,const std::string & mime_type,bool isEdited)142 int32_t FileUtils::SavePicture(const string &path, std::shared_ptr<Media::Picture> &picture,
143     const std::string &mime_type, bool isEdited)
144 {
145     MEDIA_INFO_LOG("SavePicture width %{public}d, heigh %{public}d, mime_type %{public}sd",
146         picture->GetMainPixel()->GetWidth(), picture->GetMainPixel()->GetHeight(), mime_type.c_str());
147     return DealPicture(mime_type, path, picture);
148 }
149 
DealPicture(const std::string & mime_type,const std::string & path,std::shared_ptr<Media::Picture> & picture)150 int32_t FileUtils::DealPicture(const std::string &mime_type, const std::string &path,
151     std::shared_ptr<Media::Picture> &picture)
152 {
153     MediaLibraryTracer tracer;
154     tracer.Start("FileUtils::DealPicture");
155     MEDIA_INFO_LOG("DealPicture, path: %{public}s, mime_type: %{public}s",
156         MediaFileUtils::DesensitizePath(path).c_str(), mime_type.c_str());
157     if (picture == nullptr) {
158         MEDIA_ERR_LOG("picture is nullptr.");
159         return -1;
160     }
161     Media::ImagePacker imagePacker;
162     Media::PackOption packOption;
163     packOption.format = mime_type;
164     packOption.needsPackProperties = true;
165     packOption.desiredDynamicRange = EncodeDynamicRange::AUTO;
166     packOption.isEditScene = false;
167     size_t lastSlash = path.rfind('/');
168     CHECK_AND_RETURN_RET_LOG(lastSlash != string::npos && path.size() > (lastSlash + 1), E_INVALID_VALUES,
169         "Failed to check outputPath: %{public}s", path.c_str());
170     string tempOutputPath = path.substr(0, lastSlash) + "/temp_" + path.substr(lastSlash + 1);
171     int32_t ret = MediaFileUtils::CreateAsset(tempOutputPath);
172     CHECK_AND_RETURN_RET_LOG(ret == E_SUCCESS, E_HAS_FS_ERROR,
173         "Failed to create temp filters file %{private}s", tempOutputPath.c_str());
174     imagePacker.StartPacking(tempOutputPath, packOption);
175     imagePacker.AddPicture(*(picture));
176     imagePacker.FinalizePacking();
177     size_t size = -1;
178     MediaFileUtils::GetFileSize(tempOutputPath, size);
179     MEDIA_INFO_LOG("SavePicture end size: {public}%zu", size);
180     if (size == 0) {
181         CHECK_AND_PRINT_LOG(MediaFileUtils::DeleteFile(tempOutputPath),
182             "Failed to delete temp filters file, errno: %{public}d", errno);
183         return E_OK;
184     }
185     ret = rename(tempOutputPath.c_str(), path.c_str());
186     if (MediaFileUtils::IsFileExists(tempOutputPath)) {
187         MEDIA_INFO_LOG("file: %{public}s exists and needs to be deleted", tempOutputPath.c_str());
188         if (!MediaFileUtils::DeleteFile(tempOutputPath)) {
189             MEDIA_ERR_LOG("delete file: %{public}s failed", tempOutputPath.c_str());
190         }
191     }
192     return ret;
193 }
194 
SaveVideo(const std::string & filePath,bool isEdited)195 int32_t FileUtils::SaveVideo(const std::string &filePath, bool isEdited)
196 {
197     string tempPath = filePath.substr(0, filePath.rfind('.')) + "_tmp" + filePath.substr(filePath.rfind('.'));
198     string targetPath = filePath;
199     if (isEdited) {
200         targetPath = MediaLibraryAssetOperations::GetEditDataSourcePath(filePath);
201     }
202 
203     if (!IsFileExist(tempPath)) {
204         MEDIA_ERR_LOG("file not exist: %{public}s", DfxUtils::GetSafePath(tempPath).c_str());
205     }
206 
207     if (!IsFileExist(targetPath)) {
208         MEDIA_ERR_LOG("file not exist: %{public}s", DfxUtils::GetSafePath(filePath).c_str());
209     }
210 
211     MEDIA_INFO_LOG("video rename targetPath: %{public}s, tempPath: %{public}s",
212         DfxUtils::GetSafePath(targetPath).c_str(), DfxUtils::GetSafePath(tempPath).c_str());
213     return rename(tempPath.c_str(), targetPath.c_str());
214 }
215 
SaveMovingPhotoVideo(const std::string & filePath)216 int32_t FileUtils::SaveMovingPhotoVideo(const std::string &filePath)
217 {
218     string tempPath = MovingPhotoFileUtils::GetMovingPhotoVideoPath(
219         filePath.substr(0, filePath.rfind('.')) + "_tmp" + filePath.substr(filePath.rfind('.')));
220     string targetPath;
221 
222     string videoPath = MovingPhotoFileUtils::GetMovingPhotoVideoPath(filePath);
223     string editVideoPath = MovingPhotoFileUtils::GetMovingPhotoVideoPath(
224         MediaLibraryAssetOperations::GetEditDataSourcePath(filePath));
225 
226     if (!IsFileExist(tempPath)) {
227         MEDIA_ERR_LOG("file not exist: %{public}s", DfxUtils::GetSafePath(tempPath).c_str());
228     }
229 
230     if (IsFileExist(editVideoPath)) {
231         targetPath = editVideoPath;
232     } else if (IsFileExist(videoPath)) {
233         targetPath = videoPath;
234     } else {
235         MEDIA_ERR_LOG("file not exist: %{public}s", DfxUtils::GetSafePath(filePath).c_str());
236     }
237 
238     MEDIA_INFO_LOG("video rename targetPath: %{public}s, tempPath: %{public}s",
239         DfxUtils::GetSafePath(targetPath).c_str(), DfxUtils::GetSafePath(tempPath).c_str());
240     return rename(tempPath.c_str(), targetPath.c_str());
241 }
242 
DeleteTempVideoFile(const std::string & filePath)243 int32_t FileUtils::DeleteTempVideoFile(const std::string &filePath)
244 {
245     MEDIA_INFO_LOG("filePath: %{public}s", filePath.c_str());
246     string tempPath = filePath.substr(0, filePath.rfind('.')) + "_tmp" + filePath.substr(filePath.rfind('.'));
247     if (IsFileExist(tempPath)) {
248         return DeleteFile(tempPath);
249     }
250     return E_OK;
251 }
252 } // namespace Media
253 } // namespace OHOS